1 /* vm/jit/powerpc/codegen.c - machine code generator for 32-bit powerpc
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
30 Changes: Christian Thalinger
32 $Id: codegen.c 2190 2005-04-02 10:07:44Z edwin $
41 #include "cacao/cacao.h"
42 #include "native/native.h"
43 #include "vm/builtin.h"
44 #include "vm/global.h"
45 #include "vm/loader.h"
46 #include "vm/tables.h"
47 #include "vm/jit/asmpart.h"
48 #include "vm/jit/jit.h"
49 #include "vm/jit/parse.h"
50 #include "vm/jit/reg.h"
51 #include "vm/jit/powerpc/arch.h"
52 #include "vm/jit/powerpc/codegen.h"
53 #include "vm/jit/powerpc/types.h"
56 /* register descripton - array ************************************************/
58 /* #define REG_RES 0 reserved register for OS or code generator */
59 /* #define REG_RET 1 return value register */
60 /* #define REG_EXC 2 exception value register (only old jit) */
61 /* #define REG_SAV 3 (callee) saved register */
62 /* #define REG_TMP 4 scratch temporary register (caller saved) */
63 /* #define REG_ARG 5 argument register (caller saved) */
65 /* #define REG_END -1 last entry in tables */
67 static int nregdescint[] = {
68 REG_RES, REG_RES, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
69 REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV,
70 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
71 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
74 /* for use of reserved registers, see comment above */
76 static int nregdescfloat[] = {
77 REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
78 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV,
79 REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
80 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
84 /* Include independent code generation stuff -- include after register */
85 /* descriptions to avoid extern definitions. */
87 #include "vm/jit/codegen.inc"
88 #include "vm/jit/reg.inc"
90 #include "vm/jit/lsra.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 #if defined(__DARWIN__)
106 #include <mach/message.h>
108 int cacao_catch_Handler(mach_port_t thread)
110 #if defined(USE_THREADS)
112 unsigned int crashpc;
114 java_objectheader *xptr;
117 thread_state_flavor_t flavor = PPC_THREAD_STATE;
118 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
119 ppc_thread_state_t thread_state;
125 r = thread_get_state(thread, flavor,
126 (natural_t*)&thread_state, &thread_state_count);
127 if (r != KERN_SUCCESS)
128 panic("thread_get_state failed");
130 regs = &thread_state.r0;
131 crashpc = thread_state.srr0;
133 instr = *(s4*) crashpc;
134 reg = (instr >> 16) & 31;
137 /* This is now handled in asmpart because it needs to run in the throwing
139 /* xptr = new_nullpointerexception(); */
141 regs[REG_ITMP2_XPC] = crashpc;
142 /* regs[REG_ITMP1_XPTR] = (u4) xptr; */
143 thread_state.srr0 = (u4) asm_handle_nullptr_exception;
145 r = thread_set_state(thread, flavor,
146 (natural_t*)&thread_state, thread_state_count);
147 if (r != KERN_SUCCESS)
148 panic("thread_set_state failed");
153 throw_cacao_exception_exit(string_java_lang_InternalError, "Segmentation fault at %p", regs[reg]);
158 #endif /* __DARWIN__ */
161 void init_exceptions(void)
165 #if !defined(__DARWIN__)
166 nregdescint[2] = REG_RES;
170 void adjust_argvars(stackptr s, int d, int *fa, int *ia)
176 adjust_argvars(s->prev, d-1, fa, ia);
177 if (s->varkind == ARGVAR)
178 s->varnum = (IS_FLT_DBL_TYPE(s->type)) ? *fa : *ia;
179 *fa += (IS_FLT_DBL_TYPE(s->type) != 0);
180 *ia += (IS_2_WORD_TYPE(s->type)) ? 2 : 1;
184 #define intmaxf(a,b) (((a)<(b)) ? (b) : (a))
186 void preregpass(methodinfo *m, registerdata *rd)
196 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
198 for (iptr = bptr->iinstr, src = bptr->instack;
200 src = iptr->dst, len--, iptr++)
202 if (bptr->flags < BBREACHED)
215 case ICMD_INVOKEVIRTUAL:
216 case ICMD_INVOKESPECIAL:
217 case ICMD_INVOKESTATIC:
218 case ICMD_INVOKEINTERFACE:
223 adjust_argvars(src, s3, &fa, &ia);
226 for (; --s3 >= 0; src = src->prev) {
227 paramsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
229 rd->ifmemuse = intmaxf(rd->ifmemuse, paramsize);
232 case ICMD_MULTIANEWARRAY:
234 paramsize = rd->intreg_argnum + s3;
235 rd->ifmemuse = intmaxf(rd->ifmemuse, paramsize);
242 rd->maxmemuse = rd->ifmemuse;
246 /* function gen_mcode **********************************************************
248 generates machine code
250 *******************************************************************************/
252 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
254 s4 len, s1, s2, s3, d;
270 /* space to save used callee saved registers */
272 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
273 savedregs_num += 2 * (rd->savfltregcnt - rd->maxsavfltreguse);
275 parentargs_base = rd->maxmemuse + savedregs_num;
277 #ifdef USE_THREADS /* space to save argument of monitor_enter */
279 if (checksync && (m->flags & ACC_SYNCHRONIZED))
284 /* create method header */
286 parentargs_base = (parentargs_base + 3) & ~3;
289 (void) dseg_addaddress(cd, m); /* Filler */
291 (void) dseg_addaddress(cd, m); /* MethodPointer */
292 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
296 /* IsSync contains the offset relative to the stack pointer for the
297 argument of monitor_exit used in the exception handler. Since the
298 offset could be zero and give a wrong meaning of the flag it is
302 if (checksync && (m->flags & ACC_SYNCHRONIZED))
303 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 4); /* IsSync */
308 (void) dseg_adds4(cd, 0); /* IsSync */
310 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
311 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
312 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
313 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
315 /* create exception table */
317 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
318 dseg_addtarget(cd, ex->start);
319 dseg_addtarget(cd, ex->end);
320 dseg_addtarget(cd, ex->handler);
321 (void) dseg_addaddress(cd, ex->catchtype.cls);
324 /* initialize mcode variables */
326 mcodeptr = (s4 *) cd->mcodebase;
327 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
328 MCODECHECK(128 + m->paramcount);
330 /* create stack frame (if necessary) */
332 if (!m->isleafmethod) {
334 M_AST(REG_ITMP3, REG_SP, 8);
337 if (parentargs_base) {
338 M_STWU(REG_SP, REG_SP, -parentargs_base * 4);
341 /* save return address and used callee saved registers */
344 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
345 p--; M_IST(rd->savintregs[i], REG_SP, 4 * p);
347 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
348 p-=2; M_DST(rd->savfltregs[i], REG_SP, 4 * p);
351 /* save monitorenter argument */
353 #if defined(USE_THREADS)
354 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
355 if (m->flags & ACC_STATIC) {
356 p = dseg_addaddress(cd, m->class);
357 M_ALD(REG_ITMP1, REG_PV, p);
358 M_AST(REG_ITMP1, REG_SP, 4 * rd->maxmemuse);
361 M_AST(rd->argintregs[0], REG_SP, 4 * rd->maxmemuse);
366 /* copy argument registers to stack and call trace function with pointer
367 to arguments on stack.
376 /* XXX must be a multiple of 16 */
377 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
379 M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
381 M_CLR(REG_ITMP1); /* clear help register */
383 /* save all arguments into the reserved stack space */
384 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
385 t = m->paramtypes[p];
387 if (IS_INT_LNG_TYPE(t)) {
388 /* overlapping u8's are on the stack */
389 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
390 s1 = rd->argintregs[p + longargs + dblargs];
392 if (!IS_2_WORD_TYPE(t)) {
393 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
394 M_IST(s1, REG_SP, 24 + p * 8 + 4);
397 M_IST(s1, REG_SP, 24 + p * 8);
398 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
403 a = dseg_adds4(cd, 0xdeadbeef);
404 M_ILD(REG_ITMP1, REG_PV, a);
405 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
406 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
410 if ((fltargs + dblargs) < FLT_ARG_CNT) {
411 s1 = rd->argfltregs[fltargs + dblargs];
413 if (!IS_2_WORD_TYPE(t)) {
414 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
415 M_FST(s1, REG_SP, 24 + p * 8 + 4);
419 M_DST(s1, REG_SP, 24 + p * 8);
424 /* this should not happen */
429 /* TODO: save remaining integer and flaot argument registers */
431 /* load first 4 arguments into integer argument registers */
432 for (p = 0; p < 8; p++) {
433 d = rd->argintregs[p];
434 M_ILD(d, REG_SP, 24 + p * 4);
437 p = dseg_addaddress(cd, m);
438 M_ALD(REG_ITMP1, REG_PV, p);
439 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
440 p = dseg_addaddress(cd, (void *) builtin_trace_args);
441 M_ALD(REG_ITMP2, REG_PV, p);
449 /* restore arguments into the reserved stack space */
450 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
451 t = m->paramtypes[p];
453 if (IS_INT_LNG_TYPE(t)) {
454 if ((p + longargs + dblargs) < INT_ARG_CNT) {
455 s1 = rd->argintregs[p + longargs + dblargs];
457 if (!IS_2_WORD_TYPE(t)) {
458 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
461 M_ILD(s1, REG_SP, 24 + p * 8);
462 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
468 if ((fltargs + dblargs) < FLT_ARG_CNT) {
469 s1 = rd->argfltregs[fltargs + dblargs];
471 if (!IS_2_WORD_TYPE(t)) {
472 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
476 M_DLD(s1, REG_SP, 24 + p * 8);
483 M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
485 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
489 /* take arguments out of register or stack frame */
495 for (p = 0, l = 0; p < m->paramcount; p++) {
496 arg = narg; iarg = niarg;
497 t = m->paramtypes[p];
498 var = &(rd->locals[l][t]);
500 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
504 if (IS_INT_LNG_TYPE(t)) { /* integer args */
505 if (iarg < INT_ARG_CNT -
506 (IS_2_WORD_TYPE(t)!=0)) { /* register arguments */
507 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
508 M_TINTMOVE(t, rd->argintregs[iarg], var->regoff);
510 } else { /* reg arg -> spilled */
511 M_IST(rd->argintregs[iarg], REG_SP, 4 * var->regoff);
512 if (IS_2_WORD_TYPE(t))
513 M_IST(rd->secondregs[rd->argintregs[iarg]], REG_SP, 4 * var->regoff + 4);
516 } else { /* stack arguments */
518 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
519 M_ILD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
520 if (IS_2_WORD_TYPE(t))
521 M_ILD(rd->secondregs[var->regoff], REG_SP, 4 * (parentargs_base + pa) + 4);
523 } else { /* stack arg -> spilled */
524 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa));
525 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff);
526 if (IS_2_WORD_TYPE(t)) {
527 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa) + 4);
528 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff + 4);
533 } else { /* floating args */
535 if (arg < FLT_ARG_CNT) { /* register arguments */
536 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
537 M_FLTMOVE(rd->argfltregs[arg], var->regoff);
539 } else { /* reg arg -> spilled */
540 M_DST(rd->argfltregs[arg], REG_SP, 4 * var->regoff);
543 } else { /* stack arguments */
545 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
546 if (IS_2_WORD_TYPE(t)) {
547 M_DLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
550 M_FLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
553 } else { /* stack-arg -> spilled */
554 if (IS_2_WORD_TYPE(t)) {
555 M_DLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
558 M_FLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
560 M_DST(REG_FTMP1, REG_SP, 4 * var->regoff);
567 /* call monitorenter function */
569 #if defined(USE_THREADS)
570 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
571 s4 func_enter = (m->flags & ACC_STATIC) ?
572 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
573 p = dseg_addaddress(cd, (void *) func_enter);
574 M_ALD(REG_ITMP3, REG_PV, p);
576 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
582 /* end of header generation */
584 /* walk through all basic blocks */
585 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
587 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
589 if (bptr->flags >= BBREACHED) {
591 /* branch resolving */
595 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
596 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
602 /* copy interface registers to their destination */
610 while (src != NULL) {
612 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
613 /* d = reg_of_var(m, src, REG_ITMP1); */
614 if (!(src->flags & INMEMORY))
618 M_INTMOVE(REG_ITMP1, d);
619 store_reg_to_var_int(src, d);
625 while (src != NULL) {
627 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
628 d = reg_of_var(rd, src, REG_ITMP1);
629 M_INTMOVE(REG_ITMP1, d);
630 store_reg_to_var_int(src, d);
633 d = reg_of_var(rd, src, REG_IFTMP);
634 if ((src->varkind != STACKVAR)) {
636 if (IS_FLT_DBL_TYPE(s2)) {
637 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
638 s1 = rd->interfaces[len][s2].regoff;
642 if (IS_2_WORD_TYPE(s2)) {
643 M_DLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
646 M_FLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
649 store_reg_to_var_flt(src, d);
652 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
653 s1 = rd->interfaces[len][s2].regoff;
657 M_ILD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
658 if (IS_2_WORD_TYPE(s2))
659 M_ILD(rd->secondregs[d], REG_SP, 4 * rd->interfaces[len][s2].regoff + 4);
661 store_reg_to_var_int(src, d);
671 /* walk through all instructions */
675 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
677 MCODECHECK(64); /* an instruction usually needs < 64 words */
680 case ICMD_NOP: /* ... ==> ... */
683 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
685 var_to_reg_int(s1, src, REG_ITMP1);
688 codegen_addxnullrefs(cd, mcodeptr);
691 /* constant operations ************************************************/
693 case ICMD_ICONST: /* ... ==> ..., constant */
694 /* op1 = 0, val.i = constant */
696 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
697 ICONST(d, iptr->val.i);
698 store_reg_to_var_int(iptr->dst, d);
701 case ICMD_LCONST: /* ... ==> ..., constant */
702 /* op1 = 0, val.l = constant */
704 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
705 LCONST(d, iptr->val.l);
706 store_reg_to_var_int(iptr->dst, d);
709 case ICMD_FCONST: /* ... ==> ..., constant */
710 /* op1 = 0, val.f = constant */
712 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
713 a = dseg_addfloat(cd, iptr->val.f);
715 store_reg_to_var_flt(iptr->dst, d);
718 case ICMD_DCONST: /* ... ==> ..., constant */
719 /* op1 = 0, val.d = constant */
721 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
722 a = dseg_adddouble(cd, iptr->val.d);
724 store_reg_to_var_flt(iptr->dst, d);
727 case ICMD_ACONST: /* ... ==> ..., constant */
728 /* op1 = 0, val.a = constant */
730 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
731 ICONST(d, (u4) iptr->val.a);
732 store_reg_to_var_int(iptr->dst, d);
736 /* load/store operations **********************************************/
738 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
739 case ICMD_LLOAD: /* op1 = local variable */
742 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
743 if ((iptr->dst->varkind == LOCALVAR) &&
744 (iptr->dst->varnum == iptr->op1))
746 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
747 if (var->flags & INMEMORY) {
748 M_ILD(d, REG_SP, 4 * var->regoff);
749 if (IS_2_WORD_TYPE(var->type))
750 M_ILD(rd->secondregs[d], REG_SP, 4 * var->regoff + 4);
752 M_TINTMOVE(var->type, var->regoff, d);
754 store_reg_to_var_int(iptr->dst, d);
757 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
758 case ICMD_DLOAD: /* op1 = local variable */
760 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
761 if ((iptr->dst->varkind == LOCALVAR) &&
762 (iptr->dst->varnum == iptr->op1))
764 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
765 if (var->flags & INMEMORY)
766 if (IS_2_WORD_TYPE(var->type))
767 M_DLD(d, REG_SP, 4 * var->regoff);
769 M_FLD(d, REG_SP, 4 * var->regoff);
771 M_FLTMOVE(var->regoff, d);
773 store_reg_to_var_flt(iptr->dst, d);
777 case ICMD_ISTORE: /* ..., value ==> ... */
778 case ICMD_LSTORE: /* op1 = local variable */
781 if ((src->varkind == LOCALVAR) &&
782 (src->varnum == iptr->op1))
784 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
785 if (var->flags & INMEMORY) {
786 var_to_reg_int(s1, src, REG_ITMP1);
787 M_IST(s1, REG_SP, 4 * var->regoff);
788 if (IS_2_WORD_TYPE(var->type))
789 M_IST(rd->secondregs[s1], REG_SP, 4 * var->regoff + 4);
791 var_to_reg_int(s1, src, var->regoff);
792 M_TINTMOVE(var->type, s1, var->regoff);
796 case ICMD_FSTORE: /* ..., value ==> ... */
797 case ICMD_DSTORE: /* op1 = local variable */
799 if ((src->varkind == LOCALVAR) &&
800 (src->varnum == iptr->op1))
802 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
803 if (var->flags & INMEMORY) {
804 var_to_reg_flt(s1, src, REG_FTMP1);
805 if (var->type == TYPE_DBL)
806 M_DST(s1, REG_SP, 4 * var->regoff);
808 M_FST(s1, REG_SP, 4 * var->regoff);
810 var_to_reg_flt(s1, src, var->regoff);
811 M_FLTMOVE(s1, var->regoff);
816 /* pop/dup/swap operations ********************************************/
818 /* attention: double and longs are only one entry in CACAO ICMDs */
820 case ICMD_POP: /* ..., value ==> ... */
821 case ICMD_POP2: /* ..., value, value ==> ... */
824 case ICMD_DUP: /* ..., a ==> ..., a, a */
825 M_COPY(src, iptr->dst);
828 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
830 M_COPY(src, iptr->dst);
831 M_COPY(src->prev, iptr->dst->prev);
832 M_COPY(iptr->dst, iptr->dst->prev->prev);
835 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
837 M_COPY(src, iptr->dst);
838 M_COPY(src->prev, iptr->dst->prev);
839 M_COPY(src->prev->prev, iptr->dst->prev->prev);
840 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
843 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
845 M_COPY(src, iptr->dst);
846 M_COPY(src->prev, iptr->dst->prev);
849 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
851 M_COPY(src, iptr->dst);
852 M_COPY(src->prev, iptr->dst->prev);
853 M_COPY(src->prev->prev, iptr->dst->prev->prev);
854 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
855 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
858 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
860 M_COPY(src, iptr->dst);
861 M_COPY(src->prev, iptr->dst->prev);
862 M_COPY(src->prev->prev, iptr->dst->prev->prev);
863 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
864 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
865 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
868 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
870 M_COPY(src, iptr->dst->prev);
871 M_COPY(src->prev, iptr->dst);
875 /* integer operations *************************************************/
877 case ICMD_INEG: /* ..., value ==> ..., - value */
879 var_to_reg_int(s1, src, REG_ITMP1);
880 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
882 store_reg_to_var_int(iptr->dst, d);
885 case ICMD_LNEG: /* ..., value ==> ..., - value */
887 var_to_reg_int(s1, src, REG_ITMP1);
888 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
889 M_SUBFIC(rd->secondregs[s1], 0, rd->secondregs[d]);
891 store_reg_to_var_int(iptr->dst, d);
894 case ICMD_I2L: /* ..., value ==> ..., value */
896 var_to_reg_int(s1, src, REG_ITMP2);
897 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
898 M_INTMOVE(s1, rd->secondregs[d]);
899 M_SRA_IMM(rd->secondregs[d], 31, d);
900 store_reg_to_var_int(iptr->dst, d);
903 case ICMD_L2I: /* ..., value ==> ..., value */
905 var_to_reg_int0(s1, src, REG_ITMP2, 0, 1);
906 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
908 store_reg_to_var_int(iptr->dst, d);
911 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
913 var_to_reg_int(s1, src, REG_ITMP1);
914 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
916 store_reg_to_var_int(iptr->dst, d);
919 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
921 var_to_reg_int(s1, src, REG_ITMP1);
922 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
924 store_reg_to_var_int(iptr->dst, d);
927 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
929 var_to_reg_int(s1, src, REG_ITMP1);
930 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
932 store_reg_to_var_int(iptr->dst, d);
936 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
938 var_to_reg_int(s1, src->prev, REG_ITMP1);
939 var_to_reg_int(s2, src, REG_ITMP2);
940 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
942 store_reg_to_var_int(iptr->dst, d);
945 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
946 /* val.i = constant */
948 var_to_reg_int(s1, src, REG_ITMP1);
949 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
950 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
951 M_IADD_IMM(s1, iptr->val.i, d);
954 ICONST(REG_ITMP2, iptr->val.i);
955 M_IADD(s1, REG_ITMP2, d);
957 store_reg_to_var_int(iptr->dst, d);
960 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
962 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
963 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
964 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
965 M_ADDC(s1, s2, rd->secondregs[d]);
966 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
967 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
969 store_reg_to_var_int(iptr->dst, d);
972 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
973 /* val.l = constant */
975 s3 = iptr->val.l & 0xffffffff;
976 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
977 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
978 if ((s3 >= -32768) && (s3 <= 32767)) {
979 M_ADDIC(s1, s3, rd->secondregs[d]);
982 ICONST(REG_ITMP2, s3);
983 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
985 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
986 s3 = iptr->val.l >> 32;
992 ICONST(REG_ITMP3, s3);
993 M_ADDE(s1, REG_ITMP3, d);
995 store_reg_to_var_int(iptr->dst, d);
998 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1000 var_to_reg_int(s1, src->prev, REG_ITMP1);
1001 var_to_reg_int(s2, src, REG_ITMP2);
1002 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1004 store_reg_to_var_int(iptr->dst, d);
1007 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1008 /* val.i = constant */
1010 var_to_reg_int(s1, src, REG_ITMP1);
1011 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1012 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
1013 M_IADD_IMM(s1, -iptr->val.i, d);
1016 ICONST(REG_ITMP2, -iptr->val.i);
1017 M_IADD(s1, REG_ITMP2, d);
1019 store_reg_to_var_int(iptr->dst, d);
1022 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1024 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1025 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1026 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1027 M_SUBC(s1, s2, rd->secondregs[d]);
1028 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1029 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1031 store_reg_to_var_int(iptr->dst, d);
1034 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1035 /* val.l = constant */
1037 s3 = (-iptr->val.l) & 0xffffffff;
1038 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1039 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1040 if ((s3 >= -32768) && (s3 <= 32767)) {
1041 M_ADDIC(s1, s3, rd->secondregs[d]);
1044 ICONST(REG_ITMP2, s3);
1045 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
1047 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1048 s3 = (-iptr->val.l) >> 32;
1054 ICONST(REG_ITMP3, s3);
1055 M_ADDE(s1, REG_ITMP3, d);
1057 store_reg_to_var_int(iptr->dst, d);
1060 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1061 var_to_reg_int(s1, src->prev, REG_ITMP1);
1062 var_to_reg_int(s2, src, REG_ITMP2);
1063 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1065 store_reg_to_var_int(iptr->dst, d);
1068 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1069 var_to_reg_int(s1, src->prev, REG_ITMP1);
1070 var_to_reg_int(s2, src, REG_ITMP2);
1071 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1075 store_reg_to_var_int(iptr->dst, d);
1078 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1080 var_to_reg_int(s1, src->prev, REG_ITMP1);
1081 var_to_reg_int(s2, src, REG_ITMP2);
1082 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1084 store_reg_to_var_int(iptr->dst, d);
1087 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1088 /* val.i = constant */
1090 var_to_reg_int(s1, src, REG_ITMP1);
1091 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1092 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1093 M_IMUL_IMM(s1, iptr->val.i, d);
1096 ICONST(REG_ITMP2, iptr->val.i);
1097 M_IMUL(s1, REG_ITMP2, d);
1099 store_reg_to_var_int(iptr->dst, d);
1102 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1104 var_to_reg_int(s1, src, REG_ITMP1);
1105 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1106 M_SRA_IMM(s1, iptr->val.i, d);
1108 store_reg_to_var_int(iptr->dst, d);
1111 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1113 var_to_reg_int(s1, src->prev, REG_ITMP1);
1114 var_to_reg_int(s2, src, REG_ITMP2);
1115 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1116 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1117 M_SLL(s1, REG_ITMP3, d);
1118 store_reg_to_var_int(iptr->dst, d);
1121 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1122 /* val.i = constant */
1124 var_to_reg_int(s1, src, REG_ITMP1);
1125 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1126 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1127 store_reg_to_var_int(iptr->dst, d);
1130 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1132 var_to_reg_int(s1, src->prev, REG_ITMP1);
1133 var_to_reg_int(s2, src, REG_ITMP2);
1134 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1135 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1136 M_SRA(s1, REG_ITMP3, d);
1137 store_reg_to_var_int(iptr->dst, d);
1140 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1141 /* val.i = constant */
1143 var_to_reg_int(s1, src, REG_ITMP1);
1144 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1145 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1146 store_reg_to_var_int(iptr->dst, d);
1149 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1151 var_to_reg_int(s1, src->prev, REG_ITMP1);
1152 var_to_reg_int(s2, src, REG_ITMP2);
1153 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1154 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1155 M_SRL(s1, REG_ITMP2, d);
1156 store_reg_to_var_int(iptr->dst, d);
1159 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1160 /* val.i = constant */
1162 var_to_reg_int(s1, src, REG_ITMP1);
1163 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1164 if (iptr->val.i & 0x1f)
1165 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1168 store_reg_to_var_int(iptr->dst, d);
1171 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1173 var_to_reg_int(s1, src->prev, REG_ITMP1);
1174 var_to_reg_int(s2, src, REG_ITMP2);
1175 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1177 store_reg_to_var_int(iptr->dst, d);
1180 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1181 /* val.i = constant */
1183 var_to_reg_int(s1, src, REG_ITMP1);
1184 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1185 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1186 M_AND_IMM(s1, iptr->val.i, d);
1189 else if (iptr->val.i == 0xffffff) {
1190 M_RLWINM(s1, 0, 8, 31, d);
1194 ICONST(REG_ITMP2, iptr->val.i);
1195 M_AND(s1, REG_ITMP2, d);
1197 store_reg_to_var_int(iptr->dst, d);
1200 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1202 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1203 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1204 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1205 M_AND(s1, s2, rd->secondregs[d]);
1206 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1207 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1209 store_reg_to_var_int(iptr->dst, d);
1212 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1213 /* val.l = constant */
1215 s3 = iptr->val.l & 0xffffffff;
1216 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1217 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1218 if ((s3 >= 0) && (s3 <= 65535)) {
1219 M_AND_IMM(s1, s3, rd->secondregs[d]);
1222 ICONST(REG_ITMP2, s3);
1223 M_AND(s1, REG_ITMP2, rd->secondregs[d]);
1225 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1226 s3 = iptr->val.l >> 32;
1227 if ((s3 >= 0) && (s3 <= 65535)) {
1228 M_AND_IMM(s1, s3, d);
1231 ICONST(REG_ITMP3, s3);
1232 M_AND(s1, REG_ITMP3, d);
1234 store_reg_to_var_int(iptr->dst, d);
1237 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1238 /* val.i = constant */
1240 var_to_reg_int(s1, src, REG_ITMP1);
1241 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1242 M_MOV(s1, REG_ITMP2);
1244 M_BGE(1 + 2*(iptr->val.i >= 32768));
1245 if (iptr->val.i >= 32768) {
1246 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1247 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1248 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1251 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1253 int b=0, m = iptr->val.i;
1256 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1258 M_ISUB(s1, REG_ITMP2, d);
1259 store_reg_to_var_int(iptr->dst, d);
1262 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1264 var_to_reg_int(s1, src->prev, REG_ITMP1);
1265 var_to_reg_int(s2, src, REG_ITMP2);
1266 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1268 store_reg_to_var_int(iptr->dst, d);
1271 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1272 /* val.i = constant */
1274 var_to_reg_int(s1, src, REG_ITMP1);
1275 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1276 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1277 M_OR_IMM(s1, iptr->val.i, d);
1280 ICONST(REG_ITMP2, iptr->val.i);
1281 M_OR(s1, REG_ITMP2, d);
1283 store_reg_to_var_int(iptr->dst, d);
1286 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1288 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1289 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1290 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1291 M_OR(s1, s2, rd->secondregs[d]);
1292 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1293 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1295 store_reg_to_var_int(iptr->dst, d);
1298 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1299 /* val.l = constant */
1301 s3 = iptr->val.l & 0xffffffff;
1302 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1303 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1304 if ((s3 >= 0) && (s3 <= 65535)) {
1305 M_OR_IMM(s1, s3, rd->secondregs[d]);
1308 ICONST(REG_ITMP2, s3);
1309 M_OR(s1, REG_ITMP2, rd->secondregs[d]);
1311 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1312 s3 = iptr->val.l >> 32;
1313 if ((s3 >= 0) && (s3 <= 65535)) {
1314 M_OR_IMM(s1, s3, d);
1317 ICONST(REG_ITMP3, s3);
1318 M_OR(s1, REG_ITMP3, d);
1320 store_reg_to_var_int(iptr->dst, d);
1323 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1325 var_to_reg_int(s1, src->prev, REG_ITMP1);
1326 var_to_reg_int(s2, src, REG_ITMP2);
1327 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1329 store_reg_to_var_int(iptr->dst, d);
1332 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1333 /* val.i = constant */
1335 var_to_reg_int(s1, src, REG_ITMP1);
1336 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1337 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1338 M_XOR_IMM(s1, iptr->val.i, d);
1341 ICONST(REG_ITMP2, iptr->val.i);
1342 M_XOR(s1, REG_ITMP2, d);
1344 store_reg_to_var_int(iptr->dst, d);
1347 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1349 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1350 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1351 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1352 M_XOR(s1, s2, rd->secondregs[d]);
1353 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1354 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1356 store_reg_to_var_int(iptr->dst, d);
1359 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1360 /* val.l = constant */
1362 s3 = iptr->val.l & 0xffffffff;
1363 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1364 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1365 if ((s3 >= 0) && (s3 <= 65535)) {
1366 M_XOR_IMM(s1, s3, rd->secondregs[d]);
1369 ICONST(REG_ITMP2, s3);
1370 M_XOR(s1, REG_ITMP2, rd->secondregs[d]);
1372 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1373 s3 = iptr->val.l >> 32;
1374 if ((s3 >= 0) && (s3 <= 65535)) {
1375 M_XOR_IMM(s1, s3, d);
1378 ICONST(REG_ITMP3, s3);
1379 M_XOR(s1, REG_ITMP3, d);
1381 store_reg_to_var_int(iptr->dst, d);
1384 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1386 var_to_reg_int0(s1, src->prev, REG_ITMP3, 1, 0);
1387 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
1388 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1391 (d==s1 || d==s2 || d==rd->secondregs[s1] || d==rd->secondregs[s2]);
1392 int dreg = tempreg ? REG_ITMP1 : d;
1394 M_IADD_IMM(REG_ZERO, 1, dreg);
1399 var_to_reg_int0(s1, src->prev, REG_ITMP3, 0, 1);
1400 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1404 M_IADD_IMM(dreg, -1, dreg);
1405 M_IADD_IMM(dreg, -1, dreg);
1406 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1407 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1410 store_reg_to_var_int(iptr->dst, d);
1413 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1414 /* op1 = variable, val.i = constant */
1416 var = &(rd->locals[iptr->op1][TYPE_INT]);
1417 if (var->flags & INMEMORY) {
1419 M_ILD(s1, REG_SP, 4 * var->regoff);
1428 M_ADDIS(s1, m>>16, s1);
1430 M_IADD_IMM(s1, m&0xffff, s1);
1432 if (var->flags & INMEMORY)
1433 M_IST(s1, REG_SP, 4 * var->regoff);
1437 /* floating operations ************************************************/
1439 case ICMD_FNEG: /* ..., value ==> ..., - value */
1441 var_to_reg_flt(s1, src, REG_FTMP1);
1442 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1444 store_reg_to_var_flt(iptr->dst, d);
1447 case ICMD_DNEG: /* ..., value ==> ..., - value */
1449 var_to_reg_flt(s1, src, REG_FTMP1);
1450 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1452 store_reg_to_var_flt(iptr->dst, d);
1455 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1457 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1458 var_to_reg_flt(s2, src, REG_FTMP2);
1459 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1461 store_reg_to_var_flt(iptr->dst, d);
1464 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1466 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1467 var_to_reg_flt(s2, src, REG_FTMP2);
1468 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1470 store_reg_to_var_flt(iptr->dst, d);
1473 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1475 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1476 var_to_reg_flt(s2, src, REG_FTMP2);
1477 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1479 store_reg_to_var_flt(iptr->dst, d);
1482 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1484 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1485 var_to_reg_flt(s2, src, REG_FTMP2);
1486 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1488 store_reg_to_var_flt(iptr->dst, d);
1491 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1493 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1494 var_to_reg_flt(s2, src, REG_FTMP2);
1495 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1497 store_reg_to_var_flt(iptr->dst, d);
1500 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1502 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1503 var_to_reg_flt(s2, src, REG_FTMP2);
1504 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1506 store_reg_to_var_flt(iptr->dst, d);
1509 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1511 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1512 var_to_reg_flt(s2, src, REG_FTMP2);
1513 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1515 store_reg_to_var_flt(iptr->dst, d);
1518 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1520 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1521 var_to_reg_flt(s2, src, REG_FTMP2);
1522 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1524 store_reg_to_var_flt(iptr->dst, d);
1527 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1529 var_to_reg_flt(s1, src, REG_FTMP1);
1530 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1532 a = dseg_addfloat(cd, 0.0);
1533 M_FLD(REG_FTMP2, REG_PV, a);
1534 M_FCMPU(s1, REG_FTMP2);
1536 a = dseg_adds4(cd, 0);
1537 M_CVTDL_C(s1, REG_FTMP1);
1538 M_LDA (REG_ITMP1, REG_PV, a);
1539 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1540 M_ILD (d, REG_PV, a);
1541 store_reg_to_var_int(iptr->dst, d);
1544 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1546 var_to_reg_flt(s1, src, REG_FTMP1);
1547 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1549 store_reg_to_var_flt(iptr->dst, d);
1552 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1554 var_to_reg_flt(s1, src, REG_FTMP1);
1555 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1557 store_reg_to_var_flt(iptr->dst, d);
1560 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1562 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1563 var_to_reg_flt(s2, src, REG_FTMP2);
1564 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1566 M_IADD_IMM(0, -1, d);
1569 M_IADD_IMM(0, 0, d);
1571 M_IADD_IMM(0, 1, d);
1572 store_reg_to_var_int(iptr->dst, d);
1575 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1577 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1578 var_to_reg_flt(s2, src, REG_FTMP2);
1579 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1581 M_IADD_IMM(0, 1, d);
1584 M_IADD_IMM(0, 0, d);
1586 M_IADD_IMM(0, -1, d);
1587 store_reg_to_var_int(iptr->dst, d);
1591 /* memory operations **************************************************/
1593 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1595 var_to_reg_int(s1, src, REG_ITMP1);
1596 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1597 gen_nullptr_check(s1);
1598 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1599 store_reg_to_var_int(iptr->dst, d);
1602 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1604 var_to_reg_int(s1, src->prev, REG_ITMP1);
1605 var_to_reg_int(s2, src, REG_ITMP2);
1606 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1607 if (iptr->op1 == 0) {
1608 gen_nullptr_check(s1);
1611 M_SLL_IMM(s2, 2, REG_ITMP2);
1612 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1613 M_LWZX(d, s1, REG_ITMP2);
1614 store_reg_to_var_int(iptr->dst, d);
1617 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1619 var_to_reg_int(s1, src->prev, REG_ITMP1);
1620 var_to_reg_int(s2, src, REG_ITMP2);
1621 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1622 if (iptr->op1 == 0) {
1623 gen_nullptr_check(s1);
1626 M_SLL_IMM(s2, 3, REG_ITMP2);
1627 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1628 M_ILD(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
1629 M_ILD(rd->secondregs[d], REG_ITMP2, OFFSET(java_longarray, data[0])+4);
1630 store_reg_to_var_int(iptr->dst, d);
1633 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1635 var_to_reg_int(s1, src->prev, REG_ITMP1);
1636 var_to_reg_int(s2, src, REG_ITMP2);
1637 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1638 if (iptr->op1 == 0) {
1639 gen_nullptr_check(s1);
1642 M_SLL_IMM(s2, 2, REG_ITMP2);
1643 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1644 M_LWZX(d, s1, REG_ITMP2);
1645 store_reg_to_var_int(iptr->dst, d);
1648 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1650 var_to_reg_int(s1, src->prev, REG_ITMP1);
1651 var_to_reg_int(s2, src, REG_ITMP2);
1652 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1653 if (iptr->op1 == 0) {
1654 gen_nullptr_check(s1);
1657 M_SLL_IMM(s2, 2, REG_ITMP2);
1658 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1659 M_LFSX(d, s1, REG_ITMP2);
1660 store_reg_to_var_flt(iptr->dst, d);
1663 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1665 var_to_reg_int(s1, src->prev, REG_ITMP1);
1666 var_to_reg_int(s2, src, REG_ITMP2);
1667 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1668 if (iptr->op1 == 0) {
1669 gen_nullptr_check(s1);
1672 M_SLL_IMM(s2, 3, REG_ITMP2);
1673 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1674 M_LFDX(d, s1, REG_ITMP2);
1675 store_reg_to_var_flt(iptr->dst, d);
1678 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1680 var_to_reg_int(s1, src->prev, REG_ITMP1);
1681 var_to_reg_int(s2, src, REG_ITMP2);
1682 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1683 if (iptr->op1 == 0) {
1684 gen_nullptr_check(s1);
1687 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1688 M_LBZX(d, s1, REG_ITMP2);
1690 store_reg_to_var_int(iptr->dst, d);
1693 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1695 var_to_reg_int(s1, src->prev, REG_ITMP1);
1696 var_to_reg_int(s2, src, REG_ITMP2);
1697 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1698 if (iptr->op1 == 0) {
1699 gen_nullptr_check(s1);
1702 M_SLL_IMM(s2, 1, REG_ITMP2);
1703 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1704 M_LHAX(d, s1, REG_ITMP2);
1705 store_reg_to_var_int(iptr->dst, d);
1708 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1710 var_to_reg_int(s1, src->prev, REG_ITMP1);
1711 var_to_reg_int(s2, src, REG_ITMP2);
1712 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1713 if (iptr->op1 == 0) {
1714 gen_nullptr_check(s1);
1717 M_SLL_IMM(s2, 1, REG_ITMP2);
1718 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1719 M_LHZX(d, s1, REG_ITMP2);
1720 store_reg_to_var_int(iptr->dst, d);
1723 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1725 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1726 var_to_reg_int(s2, src->prev, REG_ITMP2);
1727 if (iptr->op1 == 0) {
1728 gen_nullptr_check(s1);
1731 var_to_reg_int0(s3, src, REG_ITMP3, 1, 0);
1732 M_SLL_IMM(s2, 3, REG_ITMP2);
1733 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1734 M_STWX(s3, s1, REG_ITMP2);
1735 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1736 var_to_reg_int0(s3, src, REG_ITMP3, 0, 1);
1737 M_STWX(s3, s1, REG_ITMP2);
1740 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1742 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1743 var_to_reg_int(s2, src->prev, REG_ITMP2);
1744 if (iptr->op1 == 0) {
1745 gen_nullptr_check(s1);
1748 var_to_reg_int(s3, src, REG_ITMP3);
1749 M_SLL_IMM(s2, 2, REG_ITMP2);
1750 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1751 M_STWX(s3, s1, REG_ITMP2);
1754 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1756 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1757 var_to_reg_int(s2, src->prev, REG_ITMP2);
1758 if (iptr->op1 == 0) {
1759 gen_nullptr_check(s1);
1762 var_to_reg_flt(s3, src, REG_FTMP3);
1763 M_SLL_IMM(s2, 2, REG_ITMP2);
1764 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1765 M_STFSX(s3, s1, REG_ITMP2);
1768 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1770 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1771 var_to_reg_int(s2, src->prev, REG_ITMP2);
1772 if (iptr->op1 == 0) {
1773 gen_nullptr_check(s1);
1776 var_to_reg_flt(s3, src, REG_FTMP3);
1777 M_SLL_IMM(s2, 3, REG_ITMP2);
1778 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1779 M_STFDX(s3, s1, REG_ITMP2);
1782 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1784 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1785 var_to_reg_int(s2, src->prev, REG_ITMP2);
1786 if (iptr->op1 == 0) {
1787 gen_nullptr_check(s1);
1790 var_to_reg_int(s3, src, REG_ITMP3);
1791 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1792 M_STBX(s3, s1, REG_ITMP2);
1795 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1797 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1798 var_to_reg_int(s2, src->prev, REG_ITMP2);
1799 if (iptr->op1 == 0) {
1800 gen_nullptr_check(s1);
1803 var_to_reg_int(s3, src, REG_ITMP3);
1804 M_SLL_IMM(s2, 1, REG_ITMP2);
1805 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1806 M_STHX(s3, s1, REG_ITMP2);
1809 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1811 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1812 var_to_reg_int(s2, src->prev, REG_ITMP2);
1813 if (iptr->op1 == 0) {
1814 gen_nullptr_check(s1);
1817 var_to_reg_int(s3, src, REG_ITMP3);
1818 M_SLL_IMM(s2, 1, REG_ITMP2);
1819 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1820 M_STHX(s3, s1, REG_ITMP2);
1823 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1824 /* op1 = type, val.a = field address */
1826 /* if class isn't yet initialized, do it */
1827 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1828 /* call helper function which patches this code */
1829 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1830 M_ALD(REG_ITMP1, REG_PV, a);
1831 a = dseg_addaddress(cd, asm_check_clinit);
1832 M_ALD(REG_PV, REG_PV, a);
1837 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1839 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1841 s4 ml = -s1, mh = 0;
1842 while (ml < -32768) { ml += 65536; mh--; }
1843 M_LDA(REG_PV, REG_ITMP1, ml);
1844 M_LDAH(REG_PV, REG_PV, mh);
1848 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1849 M_ALD(REG_ITMP1, REG_PV, a);
1850 switch (iptr->op1) {
1852 var_to_reg_int(s2, src, REG_ITMP2);
1853 M_IST(s2, REG_ITMP1, 0);
1856 var_to_reg_int(s2, src, REG_ITMP3);
1857 M_IST(s2, REG_ITMP1, 0);
1858 M_IST(rd->secondregs[s2], REG_ITMP1, 4);
1861 var_to_reg_int(s2, src, REG_ITMP2);
1862 M_AST(s2, REG_ITMP1, 0);
1865 var_to_reg_flt(s2, src, REG_FTMP2);
1866 M_FST(s2, REG_ITMP1, 0);
1869 var_to_reg_flt(s2, src, REG_FTMP2);
1870 M_DST(s2, REG_ITMP1, 0);
1872 default: panic ("internal error");
1876 case ICMD_GETSTATIC: /* ... ==> ..., value */
1877 /* op1 = type, val.a = field address */
1879 /* if class isn't yet initialized, do it */
1880 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1881 /* call helper function which patches this code */
1882 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1883 M_ALD(REG_ITMP1, REG_PV, a);
1884 a = dseg_addaddress(cd, asm_check_clinit);
1885 M_ALD(REG_PV, REG_PV, a);
1890 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1892 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1894 s4 ml = -s1, mh = 0;
1895 while (ml < -32768) { ml += 65536; mh--; }
1896 M_LDA(REG_PV, REG_ITMP1, ml);
1897 M_LDAH(REG_PV, REG_PV, mh);
1901 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1902 M_ALD(REG_ITMP1, REG_PV, a);
1903 switch (iptr->op1) {
1905 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1906 M_ILD(d, REG_ITMP1, 0);
1907 store_reg_to_var_int(iptr->dst, d);
1910 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1911 M_ILD(d, REG_ITMP1, 0);
1912 M_ILD(rd->secondregs[d], REG_ITMP1, 4);
1913 store_reg_to_var_int(iptr->dst, d);
1916 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1917 M_ALD(d, REG_ITMP1, 0);
1918 store_reg_to_var_int(iptr->dst, d);
1921 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1922 M_FLD(d, REG_ITMP1, 0);
1923 store_reg_to_var_flt(iptr->dst, d);
1926 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1927 M_DLD(d, REG_ITMP1, 0);
1928 store_reg_to_var_flt(iptr->dst, d);
1930 default: panic ("internal error");
1935 case ICMD_PUTFIELD: /* ..., value ==> ... */
1936 /* op1 = type, val.i = field offset */
1938 a = ((fieldinfo *)(iptr->val.a))->offset;
1939 switch (iptr->op1) {
1941 var_to_reg_int(s1, src->prev, REG_ITMP1);
1942 var_to_reg_int(s2, src, REG_ITMP2);
1943 gen_nullptr_check(s1);
1947 var_to_reg_int(s1, src->prev, REG_ITMP1);
1948 var_to_reg_int(s2, src, REG_ITMP3);
1949 gen_nullptr_check(s1);
1951 M_IST(rd->secondregs[s2], s1, a+4);
1954 var_to_reg_int(s1, src->prev, REG_ITMP1);
1955 var_to_reg_int(s2, src, REG_ITMP2);
1956 gen_nullptr_check(s1);
1960 var_to_reg_int(s1, src->prev, REG_ITMP1);
1961 var_to_reg_flt(s2, src, REG_FTMP2);
1962 gen_nullptr_check(s1);
1966 var_to_reg_int(s1, src->prev, REG_ITMP1);
1967 var_to_reg_flt(s2, src, REG_FTMP2);
1968 gen_nullptr_check(s1);
1971 default: panic ("internal error");
1975 case ICMD_GETFIELD: /* ... ==> ..., value */
1976 /* op1 = type, val.i = field offset */
1978 a = ((fieldinfo *)(iptr->val.a))->offset;
1979 switch (iptr->op1) {
1981 var_to_reg_int(s1, src, REG_ITMP1);
1982 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1983 gen_nullptr_check(s1);
1985 store_reg_to_var_int(iptr->dst, d);
1988 var_to_reg_int(s1, src, REG_ITMP1);
1989 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1990 gen_nullptr_check(s1);
1992 M_ILD(rd->secondregs[d], s1, a+4);
1993 store_reg_to_var_int(iptr->dst, d);
1996 var_to_reg_int(s1, src, REG_ITMP1);
1997 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1998 gen_nullptr_check(s1);
2000 store_reg_to_var_int(iptr->dst, d);
2003 var_to_reg_int(s1, src, REG_ITMP1);
2004 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2005 gen_nullptr_check(s1);
2007 store_reg_to_var_flt(iptr->dst, d);
2010 var_to_reg_int(s1, src, REG_ITMP1);
2011 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2012 gen_nullptr_check(s1);
2014 store_reg_to_var_flt(iptr->dst, d);
2016 default: panic ("internal error");
2021 /* branch operations **************************************************/
2023 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2025 a = dseg_addaddress(cd, asm_handle_exception);
2026 M_ALD(REG_ITMP2, REG_PV, a);
2028 var_to_reg_int(s1, src, REG_ITMP1);
2029 M_INTMOVE(s1, REG_ITMP1_XPTR);
2031 if (m->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
2032 M_BL(0); /* get current PC */
2033 M_MFLR(REG_ITMP2_XPC);
2034 if (m->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
2035 M_RTS; /* jump to CTR */
2040 case ICMD_GOTO: /* ... ==> ... */
2041 /* op1 = target JavaVM pc */
2043 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2047 case ICMD_JSR: /* ... ==> ... */
2048 /* op1 = target JavaVM pc */
2050 if (m->isleafmethod) M_MFLR(REG_ITMP2);
2053 M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
2054 if (m->isleafmethod) M_MTLR(REG_ITMP2);
2056 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2059 case ICMD_RET: /* ... ==> ... */
2060 /* op1 = local variable */
2062 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2063 if (var->flags & INMEMORY) {
2064 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
2068 M_MTCTR(var->regoff);
2073 case ICMD_IFNULL: /* ..., value ==> ... */
2074 /* op1 = target JavaVM pc */
2076 var_to_reg_int(s1, src, REG_ITMP1);
2079 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2082 case ICMD_IFNONNULL: /* ..., value ==> ... */
2083 /* op1 = target JavaVM pc */
2085 var_to_reg_int(s1, src, REG_ITMP1);
2088 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2096 case ICMD_IFEQ: /* ..., value ==> ... */
2097 /* op1 = target JavaVM pc, val.i = constant */
2099 var_to_reg_int(s1, src, REG_ITMP1);
2100 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2101 M_CMPI(s1, iptr->val.i);
2104 ICONST(REG_ITMP2, iptr->val.i);
2105 M_CMP(s1, REG_ITMP2);
2128 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2132 case ICMD_IF_LEQ: /* ..., value ==> ... */
2133 /* op1 = target JavaVM pc, val.l = constant */
2135 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2136 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2137 if (iptr->val.l == 0) {
2138 M_OR(s1, s2, REG_ITMP3);
2139 M_CMPI(REG_ITMP3, 0);
2141 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2142 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2144 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2147 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2148 M_CMP(s2, REG_ITMP3);
2150 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2151 M_CMP(s1, REG_ITMP3)
2154 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2157 case ICMD_IF_LLT: /* ..., value ==> ... */
2158 /* op1 = target JavaVM pc, val.l = constant */
2159 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2160 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2161 /* if (iptr->val.l == 0) { */
2162 /* M_OR(s1, s2, REG_ITMP3); */
2163 /* M_CMPI(REG_ITMP3, 0); */
2166 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2167 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2169 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2171 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2174 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2175 M_CMP(s2, REG_ITMP3);
2177 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2179 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2180 M_CMP(s1, REG_ITMP3)
2183 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2186 case ICMD_IF_LLE: /* ..., value ==> ... */
2187 /* op1 = target JavaVM pc, val.l = constant */
2189 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2190 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2191 /* if (iptr->val.l == 0) { */
2192 /* M_OR(s1, s2, REG_ITMP3); */
2193 /* M_CMPI(REG_ITMP3, 0); */
2196 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2197 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2199 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2201 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2204 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2205 M_CMP(s2, REG_ITMP3);
2207 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2209 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2210 M_CMP(s1, REG_ITMP3)
2213 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2216 case ICMD_IF_LNE: /* ..., value ==> ... */
2217 /* op1 = target JavaVM pc, val.l = constant */
2219 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2220 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2221 if (iptr->val.l == 0) {
2222 M_OR(s1, s2, REG_ITMP3);
2223 M_CMPI(REG_ITMP3, 0);
2225 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2226 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2228 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2231 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2232 M_CMP(s2, REG_ITMP3);
2234 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2235 M_CMP(s1, REG_ITMP3)
2238 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2241 case ICMD_IF_LGT: /* ..., value ==> ... */
2242 /* op1 = target JavaVM pc, val.l = constant */
2244 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2245 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2246 /* if (iptr->val.l == 0) { */
2247 /* M_OR(s1, s2, REG_ITMP3); */
2248 /* M_CMPI(REG_ITMP3, 0); */
2251 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2252 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2254 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2256 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2259 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2260 M_CMP(s2, REG_ITMP3);
2262 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2264 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2265 M_CMP(s1, REG_ITMP3)
2268 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2271 case ICMD_IF_LGE: /* ..., value ==> ... */
2272 /* op1 = target JavaVM pc, val.l = constant */
2273 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2274 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2275 /* if (iptr->val.l == 0) { */
2276 /* M_OR(s1, s2, REG_ITMP3); */
2277 /* M_CMPI(REG_ITMP3, 0); */
2280 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2281 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2283 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2285 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2288 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2289 M_CMP(s2, REG_ITMP3);
2291 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2293 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2294 M_CMP(s1, REG_ITMP3)
2297 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2301 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2302 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2303 case ICMD_IF_ACMPEQ:
2305 var_to_reg_int(s1, src->prev, REG_ITMP1);
2306 var_to_reg_int(s2, src, REG_ITMP2);
2309 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2312 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2313 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2314 case ICMD_IF_ACMPNE:
2316 var_to_reg_int(s1, src->prev, REG_ITMP1);
2317 var_to_reg_int(s2, src, REG_ITMP2);
2320 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2323 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2324 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2326 var_to_reg_int(s1, src->prev, REG_ITMP1);
2327 var_to_reg_int(s2, src, REG_ITMP2);
2330 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2333 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2334 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2336 var_to_reg_int(s1, src->prev, REG_ITMP1);
2337 var_to_reg_int(s2, src, REG_ITMP2);
2340 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2343 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2344 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2346 var_to_reg_int(s1, src->prev, REG_ITMP1);
2347 var_to_reg_int(s2, src, REG_ITMP2);
2350 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2353 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2354 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2356 var_to_reg_int(s1, src->prev, REG_ITMP1);
2357 var_to_reg_int(s2, src, REG_ITMP2);
2360 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2363 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2367 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2370 case ICMD_RETURN: /* ... ==> ... */
2372 #if defined(USE_THREADS)
2373 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2374 a = dseg_addaddress(cd, (void *) (builtin_monitorexit));
2375 M_ALD(REG_ITMP3, REG_PV, a);
2377 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
2381 switch (iptr->opc) {
2385 var_to_reg_int(s1, src, REG_RESULT);
2386 M_TINTMOVE(src->type, s1, REG_RESULT);
2387 goto nowperformreturn;
2391 var_to_reg_flt(s1, src, REG_FRESULT);
2392 M_FLTMOVE(s1, REG_FRESULT);
2393 goto nowperformreturn;
2400 p = parentargs_base;
2402 /* restore return address */
2404 if (!m->isleafmethod) {
2405 M_ALD(REG_ITMP3, REG_SP, 4 * p + 8);
2409 /* restore saved registers */
2411 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2412 p--; M_ILD(rd->savintregs[i], REG_SP, 4 * p);
2414 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2415 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, 4 * p);
2418 /* deallocate stack */
2420 if (parentargs_base) {
2421 M_LDA(REG_SP, REG_SP, parentargs_base*4);
2424 /* call trace function */
2428 M_LDA(REG_SP, REG_SP, -10 * 8);
2429 M_DST(REG_FRESULT, REG_SP, 48+0);
2430 M_IST(REG_RESULT, REG_SP, 48+8);
2431 M_AST(REG_ITMP3, REG_SP, 48+12);
2432 M_IST(REG_RESULT2, REG_SP, 48+16);
2433 a = dseg_addaddress(cd, m);
2435 /* keep this order */
2436 switch (iptr->opc) {
2439 M_MOV(REG_RESULT, rd->argintregs[2]);
2440 M_CLR(rd->argintregs[1]);
2444 M_MOV(REG_RESULT2, rd->argintregs[2]);
2445 M_MOV(REG_RESULT, rd->argintregs[1]);
2448 M_ALD(rd->argintregs[0], REG_PV, a);
2450 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2451 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2452 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2453 M_ALD(REG_ITMP2, REG_PV, a);
2456 M_DLD(REG_FRESULT, REG_SP, 48+0);
2457 M_ILD(REG_RESULT, REG_SP, 48+8);
2458 M_ALD(REG_ITMP3, REG_SP, 48+12);
2459 M_ILD(REG_RESULT2, REG_SP, 48+16);
2460 M_LDA(REG_SP, REG_SP, 10 * 8);
2470 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2475 tptr = (void **) iptr->target;
2477 s4ptr = iptr->val.a;
2478 l = s4ptr[1]; /* low */
2479 i = s4ptr[2]; /* high */
2481 var_to_reg_int(s1, src, REG_ITMP1);
2483 M_INTMOVE(s1, REG_ITMP1);
2484 } else if (l <= 32768) {
2485 M_LDA(REG_ITMP1, s1, -l);
2487 ICONST(REG_ITMP2, l);
2488 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2494 M_CMPUI(REG_ITMP1, i - 1);
2497 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2498 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2500 /* build jump table top down and use address of lowest entry */
2502 /* s4ptr += 3 + i; */
2506 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2507 dseg_addtarget(cd, (basicblock *) tptr[0]);
2512 /* length of dataseg after last dseg_addtarget is used by load */
2514 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2515 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2516 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2523 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2525 s4 i, l, val, *s4ptr;
2528 tptr = (void **) iptr->target;
2530 s4ptr = iptr->val.a;
2531 l = s4ptr[0]; /* default */
2532 i = s4ptr[1]; /* count */
2534 MCODECHECK((i<<2)+8);
2535 var_to_reg_int(s1, src, REG_ITMP1);
2541 if ((val >= -32768) && (val <= 32767)) {
2545 a = dseg_adds4(cd, val);
2546 M_ILD(REG_ITMP2, REG_PV, a);
2547 M_CMP(s1, REG_ITMP2);
2550 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2551 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2555 /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2557 tptr = (void **) iptr->target;
2558 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2565 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2566 /* op1 = return type, val.a = function pointer*/
2570 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2571 /* op1 = return type, val.a = function pointer*/
2575 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2576 /* op1 = return type, val.a = function pointer*/
2580 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2581 /* op1 = arg count, val.a = method pointer */
2583 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2584 /* op1 = arg count, val.a = method pointer */
2586 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2587 /* op1 = arg count, val.a = method pointer */
2589 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2590 /* op1 = arg count, val.a = method pointer */
2598 MCODECHECK((s3 << 1) + 64);
2601 /* copy arguments to registers or stack location */
2603 stackptr srcsave = src;
2607 for (; --s3 >= 0; src = src->prev) {
2608 argsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
2609 if (IS_FLT_DBL_TYPE(src->type))
2613 for (s3 = s3save, src = srcsave; --s3 >= 0; src = src->prev) {
2614 argsize -= IS_2_WORD_TYPE(src->type) ? 2 : 1;
2615 if (IS_FLT_DBL_TYPE(src->type))
2617 if (src->varkind == ARGVAR)
2619 if (IS_INT_LNG_TYPE(src->type)) {
2620 if (argsize < INT_ARG_CNT) {
2621 s1 = rd->argintregs[argsize];
2622 var_to_reg_int(d, src, s1);
2623 if (argsize < INT_ARG_CNT-1) {
2624 M_TINTMOVE(src->type, d, s1);
2628 if (IS_2_WORD_TYPE(src->type))
2629 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2633 var_to_reg_int(d, src, REG_ITMP1);
2634 M_IST(d, REG_SP, 4 * (argsize + 6));
2635 if (IS_2_WORD_TYPE(src->type))
2636 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2640 if (fltcnt < FLT_ARG_CNT) {
2641 s1 = rd->argfltregs[fltcnt];
2642 var_to_reg_flt(d, src, s1);
2646 var_to_reg_flt(d, src, REG_FTMP1);
2647 if (IS_2_WORD_TYPE(src->type))
2648 M_DST(d, REG_SP, 4 * (argsize + 6));
2650 M_FST(d, REG_SP, 4 * (argsize + 6));
2657 switch (iptr->opc) {
2661 a = dseg_addaddress(cd, (void *) lm);
2663 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2665 goto makeactualcall;
2667 case ICMD_INVOKESTATIC:
2668 case ICMD_INVOKESPECIAL:
2669 a = dseg_addaddress(cd, lm->stubroutine);
2671 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
2674 goto makeactualcall;
2676 case ICMD_INVOKEVIRTUAL:
2678 gen_nullptr_check(rd->argintregs[0]);
2679 M_ALD(REG_METHODPTR, rd->argintregs[0],
2680 OFFSET(java_objectheader, vftbl));
2681 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) +
2682 sizeof(methodptr) * lm->vftblindex);
2685 goto makeactualcall;
2687 case ICMD_INVOKEINTERFACE:
2690 gen_nullptr_check(rd->argintregs[0]);
2691 M_ALD(REG_METHODPTR, rd->argintregs[0],
2692 OFFSET(java_objectheader, vftbl));
2693 M_ALD(REG_METHODPTR, REG_METHODPTR,
2694 OFFSET(vftbl_t, interfacetable[0]) -
2695 sizeof(methodptr*) * ci->index);
2696 M_ALD(REG_PV, REG_METHODPTR,
2697 sizeof(methodptr) * (lm - ci->methods));
2700 goto makeactualcall;
2704 error ("Unkown ICMD-Command: %d", iptr->opc);
2713 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2715 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2717 s4 ml = -s1, mh = 0;
2718 while (ml < -32768) { ml += 65536; mh--; }
2719 M_LDA(REG_PV, REG_ITMP1, ml);
2720 M_LDAH(REG_PV, REG_PV, mh);
2723 /* d contains return type */
2725 if (d != TYPE_VOID) {
2726 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2727 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2728 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2729 store_reg_to_var_int(iptr->dst, s1);
2732 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2733 M_FLTMOVE(REG_FRESULT, s1);
2734 store_reg_to_var_flt(iptr->dst, s1);
2741 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2743 /* op1: 0 == array, 1 == class */
2744 /* val.a: (classinfo*) superclass */
2746 /* superclass is an interface:
2748 * return (sub != NULL) &&
2749 * (sub->vftbl->interfacetablelength > super->index) &&
2750 * (sub->vftbl->interfacetable[-super->index] != NULL);
2752 * superclass is a class:
2754 * return ((sub != NULL) && (0
2755 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2756 * super->vftbl->diffvall));
2760 classinfo *super = (classinfo*) iptr->val.a;
2762 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2763 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2765 var_to_reg_int(s1, src, REG_ITMP1);
2766 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2768 M_MOV(s1, REG_ITMP1);
2772 if (iptr->op1) { /* class/interface */
2774 if (super->flags & ACC_INTERFACE) { /* interface */
2776 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2777 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2778 M_LDATST(REG_ITMP2, REG_ITMP2, - super->index);
2780 M_ALD(REG_ITMP1, REG_ITMP1,
2781 OFFSET(vftbl_t, interfacetable[0]) -
2782 super->index * sizeof(methodptr*));
2786 M_IADD_IMM(REG_ZERO, 1, d);
2790 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2791 a = dseg_addaddress(cd, (void*) super->vftbl);
2792 M_ALD(REG_ITMP2, REG_PV, a);
2793 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2794 codegen_threadcritstart(cd, (u1*) mcodeptr - cd->mcodebase);
2796 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2797 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2798 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2799 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2800 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2802 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2803 M_CMPU(REG_ITMP1, REG_ITMP2);
2806 M_IADD_IMM(REG_ZERO, 1, d);
2810 panic ("internal error: no inlined array instanceof");
2812 store_reg_to_var_int(iptr->dst, d);
2815 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2817 /* op1: 0 == array, 1 == class */
2818 /* val.a: (classinfo*) superclass */
2820 /* superclass is an interface:
2822 * OK if ((sub == NULL) ||
2823 * (sub->vftbl->interfacetablelength > super->index) &&
2824 * (sub->vftbl->interfacetable[-super->index] != NULL));
2826 * superclass is a class:
2828 * OK if ((sub == NULL) || (0
2829 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2830 * super->vftbl->diffvall));
2834 classinfo *super = (classinfo*) iptr->val.a;
2836 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2837 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2839 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2840 var_to_reg_int(s1, src, d);
2841 if (iptr->op1) { /* class/interface */
2843 if (super->flags & ACC_INTERFACE) { /* interface */
2845 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2846 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2847 M_LDATST(REG_ITMP3, REG_ITMP3, - super->index);
2849 codegen_addxcastrefs(cd, mcodeptr);
2850 M_ALD(REG_ITMP3, REG_ITMP2,
2851 OFFSET(vftbl_t, interfacetable[0]) -
2852 super->index * sizeof(methodptr*));
2855 codegen_addxcastrefs(cd, mcodeptr);
2858 M_BEQ(8 + (s1 == REG_ITMP1));
2859 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2860 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2861 codegen_threadcritstart(cd, (u1*) mcodeptr - cd->mcodebase);
2863 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2864 a = dseg_addaddress(cd, (void*) super->vftbl);
2865 M_ALD(REG_ITMP2, REG_PV, a);
2866 if (d != REG_ITMP1) {
2867 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2868 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2869 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2870 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2872 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2875 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2876 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2877 M_ALD(REG_ITMP2, REG_PV, a);
2878 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2879 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2880 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2883 M_CMPU(REG_ITMP3, REG_ITMP2);
2885 codegen_addxcastrefs(cd, mcodeptr);
2889 panic ("internal error: no inlined array checkcast");
2892 store_reg_to_var_int(iptr->dst, d);
2895 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
2897 var_to_reg_int(s1, src, REG_ITMP1);
2900 codegen_addxcheckarefs(cd, mcodeptr);
2903 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
2905 M_CMPI(REG_RESULT, 0);
2907 codegen_addxexceptionrefs(cd, mcodeptr);
2910 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2911 /* op1 = dimension, val.a = array descriptor */
2913 /* check for negative sizes and copy sizes to stack if necessary */
2915 MCODECHECK((iptr->op1 << 1) + 64);
2917 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
2918 var_to_reg_int(s2, src, REG_ITMP1);
2921 codegen_addxcheckarefs(cd, mcodeptr);
2923 /* copy SAVEDVAR sizes to stack */
2925 if (src->varkind != ARGVAR) {
2926 M_IST(s2, REG_SP, (s1 + INT_ARG_CNT + 6) * 4);
2930 /* a0 = dimension count */
2932 ICONST(rd->argintregs[0], iptr->op1);
2934 /* a1 = arraydescriptor */
2936 a = dseg_addaddress(cd, iptr->val.a);
2937 M_ALD(rd->argintregs[1], REG_PV, a);
2939 /* a2 = pointer to dimensions = stack pointer */
2941 M_LDA(rd->argintregs[2], REG_SP, (INT_ARG_CNT + 6) * 4);
2943 a = dseg_addaddress(cd, (void *) builtin_nmultianewarray);
2944 M_ALD(REG_PV, REG_PV, a);
2947 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2950 M_LDA (REG_PV, REG_ITMP1, -s1);
2952 s4 ml = -s1, mh = 0;
2953 while (ml < -32768) {ml += 65536; mh--;}
2954 M_LDA(REG_PV, REG_ITMP1, ml);
2955 M_LDAH(REG_PV, REG_PV, mh);
2957 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2958 M_INTMOVE(REG_RESULT, s1);
2959 store_reg_to_var_int(iptr->dst, s1);
2963 default: error ("Unknown pseudo command: %d", iptr->opc);
2967 } /* for instruction */
2969 /* copy values to interface registers */
2971 src = bptr->outstack;
2972 len = bptr->outdepth;
2973 MCODECHECK(64 + len);
2979 if ((src->varkind != STACKVAR)) {
2981 if (IS_FLT_DBL_TYPE(s2)) {
2982 var_to_reg_flt(s1, src, REG_FTMP1);
2983 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
2984 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
2987 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
2991 var_to_reg_int(s1, src, REG_ITMP1);
2992 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
2993 M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
2996 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
2997 if (IS_2_WORD_TYPE(s2))
2998 M_IST(rd->secondregs[s1], REG_SP, rd->interfaces[len][s2].regoff * 4 + 4);
3004 } /* if (bptr -> flags >= BBREACHED) */
3005 } /* for basic block */
3007 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3010 /* generate bound check stubs */
3012 s4 *xcodeptr = NULL;
3015 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3016 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3018 (u1 *) mcodeptr - cd->mcodebase);
3022 /* move index register into REG_ITMP1 */
3023 M_MOV(bref->reg, REG_ITMP1);
3024 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3026 if (xcodeptr != NULL) {
3027 M_BR(xcodeptr - mcodeptr - 1);
3030 xcodeptr = mcodeptr;
3032 M_STWU(REG_SP, REG_SP, -(24 + 2 * 4));
3033 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3035 M_MOV(REG_ITMP1, rd->argintregs[0]);
3037 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3038 M_ALD(REG_ITMP2, REG_PV, a);
3041 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3043 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3044 M_IADD_IMM(REG_SP, 24 + 2 * 4, REG_SP);
3046 a = dseg_addaddress(cd, asm_handle_exception);
3047 M_ALD(REG_ITMP3, REG_PV, a);
3054 /* generate negative array size check stubs */
3058 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3059 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3060 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3062 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3066 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3068 (u1 *) mcodeptr - cd->mcodebase);
3072 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3074 if (xcodeptr != NULL) {
3075 M_BR(xcodeptr - mcodeptr - 1);
3078 xcodeptr = mcodeptr;
3080 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3081 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3083 a = dseg_addaddress(cd, new_negativearraysizeexception);
3084 M_ALD(REG_ITMP2, REG_PV, a);
3087 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3089 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3090 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3092 a = dseg_addaddress(cd, asm_handle_exception);
3093 M_ALD(REG_ITMP3, REG_PV, a);
3100 /* generate cast check stubs */
3104 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3105 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3106 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3108 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3112 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3114 (u1 *) mcodeptr - cd->mcodebase);
3118 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3120 if (xcodeptr != NULL) {
3121 M_BR(xcodeptr - mcodeptr - 1);
3124 xcodeptr = mcodeptr;
3126 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3127 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3129 a = dseg_addaddress(cd, new_classcastexception);
3130 M_ALD(REG_ITMP2, REG_PV, a);
3133 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3135 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3136 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3138 a = dseg_addaddress(cd, asm_handle_exception);
3139 M_ALD(REG_ITMP3, REG_PV, a);
3146 /* generate exception check stubs */
3150 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3151 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3152 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3154 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3158 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3160 (u1 *) mcodeptr - cd->mcodebase);
3164 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3166 if (xcodeptr != NULL) {
3167 M_BR(xcodeptr - mcodeptr - 1);
3170 xcodeptr = mcodeptr;
3172 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3173 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3175 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3176 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3177 M_ALD(REG_ITMP2, REG_PV, a);
3181 /* get the exceptionptr from the ptrprt and clear it */
3182 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3184 M_AST(REG_ITMP3, REG_RESULT, 0);
3186 a = dseg_addaddress(cd, &_exceptionptr);
3187 M_ALD(REG_ITMP2, REG_PV, a);
3189 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);
3191 M_AST(REG_ITMP3, REG_ITMP2, 0);
3194 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3195 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3197 a = dseg_addaddress(cd, asm_handle_exception);
3198 M_ALD(REG_ITMP3, REG_PV, a);
3204 /* generate null pointer check stubs */
3208 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3209 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3210 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3212 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3216 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3218 (u1 *) mcodeptr - cd->mcodebase);
3222 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3224 if (xcodeptr != NULL) {
3225 M_BR(xcodeptr - mcodeptr - 1);
3228 xcodeptr = mcodeptr;
3230 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3231 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3233 a = dseg_addaddress(cd, new_nullpointerexception);
3234 M_ALD(REG_ITMP2, REG_PV, a);
3237 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3239 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3240 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3242 a = dseg_addaddress(cd, asm_handle_exception);
3243 M_ALD(REG_ITMP3, REG_PV, a);
3250 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
3252 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3256 /* function createcompilerstub *************************************************
3258 creates a stub routine which calls the compiler
3260 *******************************************************************************/
3262 #define COMPSTUBSIZE 6
3264 u1 *createcompilerstub(methodinfo *m)
3266 s4 *s = CNEW (s4, COMPSTUBSIZE); /* memory to hold the stub */
3267 s4 *mcodeptr = s; /* code generation pointer */
3269 M_LDA(REG_ITMP1, REG_PV, 4*4);
3270 M_ALD(REG_PV, REG_PV, 5*4);
3274 s[4] = (s4) m; /* literals to be adressed */
3275 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3277 asm_cacheflush((void*) s, (u1*) mcodeptr - (u1*) s);
3279 #if defined(STATISTICS)
3281 count_cstub_len += COMPSTUBSIZE * 4;
3288 /* function removecompilerstub *************************************************
3290 deletes a compilerstub from memory (simply by freeing it)
3292 *******************************************************************************/
3294 void removecompilerstub(u1 *stub)
3296 CFREE(stub, COMPSTUBSIZE * 4);
3300 /* function: createnativestub **************************************************
3302 creates a stub routine which calls a native method
3304 *******************************************************************************/
3306 #define NATIVESTUBSIZE 200
3307 #define NATIVESTUBOFFSET 9
3309 u1 *createnativestub(functionptr f, methodinfo *m)
3311 s4 *s; /* memory to hold the stub */
3313 s4 *mcodeptr; /* code generation pointer */
3314 s4 stackframesize = 0; /* size of stackframe if needed */
3317 t_inlining_globals *id;
3320 /* mark start of dump memory area */
3322 dumpsize = dump_size();
3324 /* setup registers before using it */
3326 rd = DNEW(registerdata);
3327 id = DNEW(t_inlining_globals);
3329 inlining_setup(m, id);
3330 reg_setup(m, rd, id);
3332 method_descriptor2types(m); /* set paramcount and paramtypes */
3334 s = CNEW(s4, NATIVESTUBSIZE);
3335 cs = s + NATIVESTUBOFFSET;
3338 *(cs-1) = (u4) f; /* address of native method */
3339 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3340 *(cs-2) = (u4) builtin_get_exceptionptrptr;
3342 *(cs-2) = (u4) (&_exceptionptr); /* address of exceptionptr */
3344 *(cs-3) = (u4) asm_handle_nat_exception; /* addr of asm exception handler */
3345 *(cs-4) = (u4) (&env); /* addr of jni_environement */
3346 *(cs-5) = (u4) builtin_trace_args;
3348 *(cs-7) = (u4) builtin_displaymethodstop;
3349 *(cs-8) = (u4) m->class;
3350 *(cs-9) = (u4) asm_check_clinit;
3353 M_AST(REG_ITMP1, REG_SP, 8); /* store return address */
3354 M_STWU(REG_SP, REG_SP, -64); /* build up stackframe */
3356 /* if function is static, check for initialized */
3358 if (m->flags & ACC_STATIC) {
3359 /* if class isn't yet initialized, do it */
3360 if (!m->class->initialized) {
3361 /* call helper function which patches this code */
3362 M_ALD(REG_ITMP1, REG_PV, -8 * 4); /* class */
3363 M_ALD(REG_PV, REG_PV, -9 * 4); /* asm_check_clinit */
3366 disp = -(s4) (mcodeptr - cs) * 4;
3368 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3378 /* M_MFLR(REG_ITMP3); */
3379 /* XXX must be a multiple of 16 */
3380 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
3382 /* M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3386 /* save all arguments into the reserved stack space */
3387 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3388 t = m->paramtypes[p];
3390 if (IS_INT_LNG_TYPE(t)) {
3391 /* overlapping u8's are on the stack */
3392 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
3393 s1 = rd->argintregs[p + longargs + dblargs];
3395 if (!IS_2_WORD_TYPE(t)) {
3396 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3397 M_IST(s1, REG_SP, 24 + p * 8 + 4);
3400 M_IST(s1, REG_SP, 24 + p * 8);
3401 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3406 /* we do not have a data segment here */
3407 /* a = dseg_adds4(cd, 0xdeadbeef);
3408 M_ILD(REG_ITMP1, REG_PV, a); */
3409 M_LDA(REG_ITMP1, REG_ZERO, -1);
3410 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3411 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
3415 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3416 s1 = rd->argfltregs[fltargs + dblargs];
3418 if (!IS_2_WORD_TYPE(t)) {
3419 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3420 M_FST(s1, REG_SP, 24 + p * 8 + 4);
3424 M_DST(s1, REG_SP, 24 + p * 8);
3429 /* this should not happen */
3434 /* TODO: save remaining integer and flaot argument registers */
3436 /* load first 4 arguments into integer argument registers */
3437 for (p = 0; p < 8; p++) {
3438 d = rd->argintregs[p];
3439 M_ILD(d, REG_SP, 24 + p * 4);
3442 M_ALD(REG_ITMP1, REG_PV, -6 * 4);
3443 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
3444 M_ALD(REG_ITMP2, REG_PV, -5 * 4);
3452 /* restore arguments into the reserved stack space */
3453 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3454 t = m->paramtypes[p];
3456 if (IS_INT_LNG_TYPE(t)) {
3457 if ((p + longargs + dblargs) < INT_ARG_CNT) {
3458 s1 = rd->argintregs[p + longargs + dblargs];
3460 if (!IS_2_WORD_TYPE(t)) {
3461 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
3464 M_ILD(s1, REG_SP, 24 + p * 8);
3465 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3471 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3472 s1 = rd->argfltregs[fltargs + dblargs];
3474 if (!IS_2_WORD_TYPE(t)) {
3475 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
3479 M_DLD(s1, REG_SP, 24 + p * 8);
3486 /* M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3488 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
3489 /* M_MTLR(REG_ITMP3); */
3492 /* save argument registers on stack -- if we have to */
3493 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) ||
3494 m->paramcount > (INT_ARG_CNT - 1)) {
3496 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3497 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3499 stackframesize = stackparamcnt + paramshiftcnt;
3501 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
3503 panic("nativestub");
3506 if (m->flags & ACC_STATIC) {
3507 M_MOV(rd->argintregs[5], rd->argintregs[7]);
3508 M_MOV(rd->argintregs[4], rd->argintregs[6]);
3509 M_MOV(rd->argintregs[3], rd->argintregs[5]);
3510 M_MOV(rd->argintregs[2], rd->argintregs[4]);
3511 M_MOV(rd->argintregs[1], rd->argintregs[3]);
3512 M_MOV(rd->argintregs[0], rd->argintregs[2]);
3514 /* put class into second argument register */
3515 M_ALD(rd->argintregs[1], REG_PV, -8 * 4);
3518 M_MOV(rd->argintregs[6], rd->argintregs[7]);
3519 M_MOV(rd->argintregs[5], rd->argintregs[6]);
3520 M_MOV(rd->argintregs[4], rd->argintregs[5]);
3521 M_MOV(rd->argintregs[3], rd->argintregs[4]);
3522 M_MOV(rd->argintregs[2], rd->argintregs[3]);
3523 M_MOV(rd->argintregs[1], rd->argintregs[2]);
3524 M_MOV(rd->argintregs[0], rd->argintregs[1]);
3527 /* put env into first argument register */
3528 M_ALD(rd->argintregs[0], REG_PV, -4 * 4);
3530 M_ALD(REG_PV, REG_PV, -1 * 4); /* load adress of native method */
3533 disp = -(s4) (mcodeptr - cs) * 4;
3535 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3537 /* remove stackframe if there is one */
3538 if (stackframesize) {
3539 M_LDA(REG_SP, REG_SP, stackframesize * 8);
3542 /* 20 instructions */
3545 M_LDA(REG_SP, REG_SP, -10 * 8);
3546 M_DST(REG_FRESULT, REG_SP, 48+0);
3547 M_IST(REG_RESULT, REG_SP, 48+8);
3548 M_AST(REG_ITMP3, REG_SP, 48+12);
3549 M_IST(REG_RESULT2, REG_SP, 48+16);
3551 /* keep this order */
3552 switch (m->returntype) {
3555 M_MOV(REG_RESULT, rd->argintregs[2]);
3556 M_CLR(rd->argintregs[1]);
3560 M_MOV(REG_RESULT2, rd->argintregs[2]);
3561 M_MOV(REG_RESULT, rd->argintregs[1]);
3564 M_ALD(rd->argintregs[0], REG_PV, -6 * 4);
3566 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
3567 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
3568 M_ALD(REG_ITMP2, REG_PV, -7 * 4);/* builtin_displaymethodstop */
3571 M_DLD(REG_FRESULT, REG_SP, 48+0);
3572 M_ILD(REG_RESULT, REG_SP, 48+8);
3573 M_ALD(REG_ITMP3, REG_SP, 48+12);
3574 M_ILD(REG_RESULT2, REG_SP, 48+16);
3575 M_LDA(REG_SP, REG_SP, 10 * 8);
3579 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3580 if (IS_FLT_DBL_TYPE(m->returntype))
3581 if (IS_2_WORD_TYPE(m->returntype))
3582 M_DST(REG_FRESULT, REG_SP, 56);
3584 M_FST(REG_FRESULT, REG_SP, 56);
3586 M_IST(REG_RESULT, REG_SP, 56);
3587 if (IS_2_WORD_TYPE(m->returntype))
3588 M_IST(REG_RESULT2, REG_SP, 60);
3591 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* builtin_get_exceptionptrptr */
3594 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3596 M_LDA(REG_PV, REG_ITMP1, disp);
3597 M_MOV(REG_RESULT, REG_ITMP2);
3599 if (IS_FLT_DBL_TYPE(m->returntype))
3600 if (IS_2_WORD_TYPE(m->returntype))
3601 M_DLD(REG_FRESULT, REG_SP, 56);
3603 M_FLD(REG_FRESULT, REG_SP, 56);
3605 M_ILD(REG_RESULT, REG_SP, 56);
3606 if (IS_2_WORD_TYPE(m->returntype))
3607 M_ILD(REG_RESULT2, REG_SP, 60);
3610 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* get address of exceptionptr */
3612 M_ALD(REG_ITMP1, REG_ITMP2, 0); /* load exception into reg. itmp1 */
3614 M_BNE(4); /* if no exception then return */
3616 M_ALD(REG_ITMP1, REG_SP, 64 + 8); /* load return address */
3618 M_LDA(REG_SP, REG_SP, 64); /* remove stackframe */
3623 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
3625 M_ALD(REG_ITMP3, REG_SP, 64 + 8); /* load return address */
3627 M_LDA(REG_SP, REG_SP, 64); /* remove stackframe */
3629 M_LDA(REG_ITMP2, REG_ITMP1, -4); /* move fault address into reg. itmp2 */
3631 M_ALD(REG_ITMP3, REG_PV, -3 * 4); /* load asm exception handler address */
3636 dolog_plain("stubsize: %d (for %d params)\n", (int) (mcodeptr - (s4 *) s), m->paramcount);
3639 asm_cacheflush((void *) s, (u1*) mcodeptr - (u1*) s);
3641 #if defined(STATISTICS)
3643 count_nstub_len += NATIVESTUBSIZE * 4;
3646 /* release dump area */
3648 dump_release(dumpsize);
3650 return (u1*) (s + NATIVESTUBOFFSET);
3654 /* function: removenativestub **************************************************
3656 removes a previously created native-stub from memory
3658 *******************************************************************************/
3660 void removenativestub(u1 *stub)
3662 CFREE((s4 *) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 4);
3667 * These are local overrides for various environment variables in Emacs.
3668 * Please do not remove this and leave it at the end of the file, where
3669 * Emacs will automagically detect them.
3670 * ---------------------------------------------------------------------
3673 * indent-tabs-mode: t