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 $Id: codegen.c 1735 2004-12-07 14:33:27Z twisti $
38 #include "native/native.h"
39 #include "vm/builtin.h"
40 #include "vm/global.h"
41 #include "vm/loader.h"
42 #include "vm/tables.h"
43 #include "vm/jit/asmpart.h"
44 #include "vm/jit/jit.h"
45 #include "vm/jit/parse.h"
46 #include "vm/jit/reg.h"
47 #include "vm/jit/powerpc/arch.h"
48 #include "vm/jit/powerpc/codegen.h"
49 #include "vm/jit/powerpc/types.h"
52 /* register descripton - array ************************************************/
54 /* #define REG_RES 0 reserved register for OS or code generator */
55 /* #define REG_RET 1 return value register */
56 /* #define REG_EXC 2 exception value register (only old jit) */
57 /* #define REG_SAV 3 (callee) saved register */
58 /* #define REG_TMP 4 scratch temporary register (caller saved) */
59 /* #define REG_ARG 5 argument register (caller saved) */
61 /* #define REG_END -1 last entry in tables */
63 static int nregdescint[] = {
64 REG_RES, REG_RES, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
65 REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV,
66 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
67 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
70 /* for use of reserved registers, see comment above */
72 static int nregdescfloat[] = {
73 REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
74 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV,
75 REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
76 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
80 /* Include independent code generation stuff -- include after register */
81 /* descriptions to avoid extern definitions. */
83 #include "vm/jit/codegen.inc"
84 #include "vm/jit/reg.inc"
86 #include "vm/jit/lsra.inc"
90 void asm_cacheflush(void *, long);
92 /* #include <architecture/ppc/cframe.h> */
94 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
95 void thread_restartcriticalsection(void *u)
97 /* XXX set pc to restart address */
101 #include <mach/message.h>
103 int cacao_catch_Handler(mach_port_t thread)
106 unsigned int crashpc;
108 java_objectheader *xptr;
111 thread_state_flavor_t flavor = PPC_THREAD_STATE;
112 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
113 ppc_thread_state_t thread_state;
119 r = thread_get_state(thread, flavor,
120 (natural_t*)&thread_state, &thread_state_count);
121 if (r != KERN_SUCCESS)
122 panic("thread_get_state failed");
124 regs = &thread_state.r0;
125 crashpc = thread_state.srr0;
127 instr = *(s4*) crashpc;
128 reg = (instr >> 16) & 31;
131 xptr = new_nullpointerexception();
133 regs[REG_ITMP2_XPC] = crashpc;
134 regs[REG_ITMP1_XPTR] = (u4) xptr;
135 thread_state.srr0 = (u4) asm_handle_exception;
137 r = thread_set_state(thread, flavor,
138 (natural_t*)&thread_state, thread_state_count);
139 if (r != KERN_SUCCESS)
140 panic("thread_set_state failed");
145 throw_cacao_exception_exit(string_java_lang_InternalError, "Segmentation fault at %p", regs[reg]);
150 void init_exceptions(void)
155 void adjust_argvars(stackptr s, int d, int *fa, int *ia)
161 adjust_argvars(s->prev, d-1, fa, ia);
162 if (s->varkind == ARGVAR)
163 s->varnum = (IS_FLT_DBL_TYPE(s->type)) ? *fa : *ia;
164 *fa += (IS_FLT_DBL_TYPE(s->type) != 0);
165 *ia += (IS_2_WORD_TYPE(s->type)) ? 2 : 1;
169 #define intmaxf(a,b) (((a)<(b)) ? (b) : (a))
171 void preregpass(methodinfo *m, registerdata *rd)
181 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
183 for (iptr = bptr->iinstr, src = bptr->instack;
185 src = iptr->dst, len--, iptr++)
187 if (bptr->flags < BBREACHED)
200 case ICMD_INVOKEVIRTUAL:
201 case ICMD_INVOKESPECIAL:
202 case ICMD_INVOKESTATIC:
203 case ICMD_INVOKEINTERFACE:
208 adjust_argvars(src, s3, &fa, &ia);
211 for (; --s3 >= 0; src = src->prev) {
212 paramsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
214 rd->ifmemuse = intmaxf(rd->ifmemuse, paramsize);
217 case ICMD_MULTIANEWARRAY:
219 paramsize = rd->intreg_argnum + s3;
220 rd->ifmemuse = intmaxf(rd->ifmemuse, paramsize);
227 rd->maxmemuse = rd->ifmemuse;
231 /* function gen_mcode **********************************************************
233 generates machine code
235 *******************************************************************************/
237 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
239 s4 len, s1, s2, s3, d;
255 /* space to save used callee saved registers */
257 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
258 savedregs_num += 2 * (rd->savfltregcnt - rd->maxsavfltreguse);
260 parentargs_base = rd->maxmemuse + savedregs_num;
262 #ifdef USE_THREADS /* space to save argument of monitor_enter */
264 if (checksync && (m->flags & ACC_SYNCHRONIZED))
269 /* create method header */
271 parentargs_base = (parentargs_base + 3) & ~3;
274 (void) dseg_addaddress(cd, m); /* Filler */
276 (void) dseg_addaddress(cd, m); /* MethodPointer */
277 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
281 /* IsSync contains the offset relative to the stack pointer for the
282 argument of monitor_exit used in the exception handler. Since the
283 offset could be zero and give a wrong meaning of the flag it is
287 if (checksync && (m->flags & ACC_SYNCHRONIZED))
288 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 4); /* IsSync */
293 (void) dseg_adds4(cd, 0); /* IsSync */
295 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
296 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
297 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
298 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
300 /* create exception table */
302 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
303 dseg_addtarget(cd, ex->start);
304 dseg_addtarget(cd, ex->end);
305 dseg_addtarget(cd, ex->handler);
306 (void) dseg_addaddress(cd, ex->catchtype);
309 /* initialize mcode variables */
311 mcodeptr = (s4 *) cd->mcodebase;
312 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
313 MCODECHECK(128 + m->paramcount);
315 /* create stack frame (if necessary) */
317 if (!m->isleafmethod) {
319 M_AST(REG_ITMP3, REG_SP, 8);
322 if (parentargs_base) {
323 M_STWU(REG_SP, REG_SP, -parentargs_base * 4);
326 /* save return address and used callee saved registers */
329 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
330 p--; M_IST(rd->savintregs[i], REG_SP, 4 * p);
332 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
333 p-=2; M_DST(rd->savfltregs[i], REG_SP, 4 * p);
336 /* save monitorenter argument */
338 #if defined(USE_THREADS)
339 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
340 if (m->flags & ACC_STATIC) {
341 p = dseg_addaddress(cd, m->class);
342 M_ALD(REG_ITMP1, REG_PV, p);
343 M_AST(REG_ITMP1, REG_SP, 4 * rd->maxmemuse);
346 M_AST(rd->argintregs[0], REG_SP, 4 * rd->maxmemuse);
351 /* copy argument registers to stack and call trace function with pointer
352 to arguments on stack.
361 /* XXX must be a multiple of 16 */
362 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
364 M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
366 M_CLR(REG_ITMP1); /* clear help register */
368 /* save all arguments into the reserved stack space */
369 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
370 t = m->paramtypes[p];
372 if (IS_INT_LNG_TYPE(t)) {
373 /* overlapping u8's are on the stack */
374 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
375 s1 = rd->argintregs[p + longargs + dblargs];
377 if (!IS_2_WORD_TYPE(t)) {
378 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
379 M_IST(s1, REG_SP, 24 + p * 8 + 4);
382 M_IST(s1, REG_SP, 24 + p * 8);
383 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
388 a = dseg_adds4(cd, 0xdeadbeef);
389 M_ILD(REG_ITMP1, REG_PV, a);
390 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
391 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
395 if ((fltargs + dblargs) < FLT_ARG_CNT) {
396 s1 = rd->argfltregs[fltargs + dblargs];
398 if (!IS_2_WORD_TYPE(t)) {
399 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
400 M_FST(s1, REG_SP, 24 + p * 8 + 4);
404 M_DST(s1, REG_SP, 24 + p * 8);
409 /* this should not happen */
414 /* TODO: save remaining integer and flaot argument registers */
416 /* load first 4 arguments into integer argument registers */
417 for (p = 0; p < 8; p++) {
418 d = rd->argintregs[p];
419 M_ILD(d, REG_SP, 24 + p * 4);
422 p = dseg_addaddress(cd, m);
423 M_ALD(REG_ITMP1, REG_PV, p);
424 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
425 p = dseg_addaddress(cd, (void *) builtin_trace_args);
426 M_ALD(REG_ITMP2, REG_PV, p);
434 /* restore arguments into the reserved stack space */
435 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
436 t = m->paramtypes[p];
438 if (IS_INT_LNG_TYPE(t)) {
439 if ((p + longargs + dblargs) < INT_ARG_CNT) {
440 s1 = rd->argintregs[p + longargs + dblargs];
442 if (!IS_2_WORD_TYPE(t)) {
443 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
446 M_ILD(s1, REG_SP, 24 + p * 8);
447 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
453 if ((fltargs + dblargs) < FLT_ARG_CNT) {
454 s1 = rd->argfltregs[fltargs + dblargs];
456 if (!IS_2_WORD_TYPE(t)) {
457 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
461 M_DLD(s1, REG_SP, 24 + p * 8);
468 M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
470 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
474 /* take arguments out of register or stack frame */
480 for (p = 0, l = 0; p < m->paramcount; p++) {
481 arg = narg; iarg = niarg;
482 t = m->paramtypes[p];
483 var = &(rd->locals[l][t]);
485 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
489 if (IS_INT_LNG_TYPE(t)) { /* integer args */
490 if (iarg < INT_ARG_CNT -
491 (IS_2_WORD_TYPE(t)!=0)) { /* register arguments */
492 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
493 M_TINTMOVE(t, rd->argintregs[iarg], var->regoff);
495 } else { /* reg arg -> spilled */
496 M_IST(rd->argintregs[iarg], REG_SP, 4 * var->regoff);
497 if (IS_2_WORD_TYPE(t))
498 M_IST(rd->secondregs[rd->argintregs[iarg]], REG_SP, 4 * var->regoff + 4);
501 } else { /* stack arguments */
503 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
504 M_ILD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
505 if (IS_2_WORD_TYPE(t))
506 M_ILD(rd->secondregs[var->regoff], REG_SP, 4 * (parentargs_base + pa) + 4);
508 } else { /* stack arg -> spilled */
509 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa));
510 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff);
511 if (IS_2_WORD_TYPE(t)) {
512 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa) + 4);
513 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff + 4);
518 } else { /* floating args */
520 if (arg < FLT_ARG_CNT) { /* register arguments */
521 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
522 M_FLTMOVE(rd->argfltregs[arg], var->regoff);
524 } else { /* reg arg -> spilled */
525 M_DST(rd->argfltregs[arg], REG_SP, 4 * var->regoff);
528 } else { /* stack arguments */
530 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
531 if (IS_2_WORD_TYPE(t)) {
532 M_DLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
535 M_FLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
538 } else { /* stack-arg -> spilled */
539 if (IS_2_WORD_TYPE(t)) {
540 M_DLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
543 M_FLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
545 M_DST(REG_FTMP1, REG_SP, 4 * var->regoff);
552 /* call monitorenter function */
554 #if defined(USE_THREADS)
555 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
556 s4 func_enter = (m->flags & ACC_STATIC) ?
557 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
558 p = dseg_addaddress(cd, (void *) func_enter);
559 M_ALD(REG_ITMP3, REG_PV, p);
561 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
567 /* end of header generation */
569 /* walk through all basic blocks */
570 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
572 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
574 if (bptr->flags >= BBREACHED) {
576 /* branch resolving */
580 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
581 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
587 /* copy interface registers to their destination */
592 while (src != NULL) {
594 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
595 d = reg_of_var(rd, src, REG_ITMP1);
596 M_INTMOVE(REG_ITMP1, d);
597 store_reg_to_var_int(src, d);
600 d = reg_of_var(rd, src, REG_IFTMP);
601 if ((src->varkind != STACKVAR)) {
603 if (IS_FLT_DBL_TYPE(s2)) {
604 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
605 s1 = rd->interfaces[len][s2].regoff;
609 if (IS_2_WORD_TYPE(s2)) {
610 M_DLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
613 M_FLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
616 store_reg_to_var_flt(src, d);
619 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
620 s1 = rd->interfaces[len][s2].regoff;
624 M_ILD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
625 if (IS_2_WORD_TYPE(s2))
626 M_ILD(rd->secondregs[d], REG_SP, 4 * rd->interfaces[len][s2].regoff + 4);
628 store_reg_to_var_int(src, d);
635 /* walk through all instructions */
639 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
641 MCODECHECK(64); /* an instruction usually needs < 64 words */
644 case ICMD_NOP: /* ... ==> ... */
647 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
649 var_to_reg_int(s1, src, REG_ITMP1);
652 codegen_addxnullrefs(cd, mcodeptr);
655 /* constant operations ************************************************/
657 case ICMD_ICONST: /* ... ==> ..., constant */
658 /* op1 = 0, val.i = constant */
660 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
661 ICONST(d, iptr->val.i);
662 store_reg_to_var_int(iptr->dst, d);
665 case ICMD_LCONST: /* ... ==> ..., constant */
666 /* op1 = 0, val.l = constant */
668 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
669 LCONST(d, iptr->val.l);
670 store_reg_to_var_int(iptr->dst, d);
673 case ICMD_FCONST: /* ... ==> ..., constant */
674 /* op1 = 0, val.f = constant */
676 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
677 a = dseg_addfloat(cd, iptr->val.f);
679 store_reg_to_var_flt(iptr->dst, d);
682 case ICMD_DCONST: /* ... ==> ..., constant */
683 /* op1 = 0, val.d = constant */
685 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
686 a = dseg_adddouble(cd, iptr->val.d);
688 store_reg_to_var_flt(iptr->dst, d);
691 case ICMD_ACONST: /* ... ==> ..., constant */
692 /* op1 = 0, val.a = constant */
694 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
695 ICONST(d, (u4) iptr->val.a);
696 store_reg_to_var_int(iptr->dst, d);
700 /* load/store operations **********************************************/
702 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
703 case ICMD_LLOAD: /* op1 = local variable */
706 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
707 if ((iptr->dst->varkind == LOCALVAR) &&
708 (iptr->dst->varnum == iptr->op1))
710 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
711 if (var->flags & INMEMORY) {
712 M_ILD(d, REG_SP, 4 * var->regoff);
713 if (IS_2_WORD_TYPE(var->type))
714 M_ILD(rd->secondregs[d], REG_SP, 4 * var->regoff + 4);
716 M_TINTMOVE(var->type, var->regoff, d);
718 store_reg_to_var_int(iptr->dst, d);
721 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
722 case ICMD_DLOAD: /* op1 = local variable */
724 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
725 if ((iptr->dst->varkind == LOCALVAR) &&
726 (iptr->dst->varnum == iptr->op1))
728 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
729 if (var->flags & INMEMORY)
730 if (IS_2_WORD_TYPE(var->type))
731 M_DLD(d, REG_SP, 4 * var->regoff);
733 M_FLD(d, REG_SP, 4 * var->regoff);
735 M_FLTMOVE(var->regoff, d);
737 store_reg_to_var_flt(iptr->dst, d);
741 case ICMD_ISTORE: /* ..., value ==> ... */
742 case ICMD_LSTORE: /* op1 = local variable */
745 if ((src->varkind == LOCALVAR) &&
746 (src->varnum == iptr->op1))
748 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
749 if (var->flags & INMEMORY) {
750 var_to_reg_int(s1, src, REG_ITMP1);
751 M_IST(s1, REG_SP, 4 * var->regoff);
752 if (IS_2_WORD_TYPE(var->type))
753 M_IST(rd->secondregs[s1], REG_SP, 4 * var->regoff + 4);
755 var_to_reg_int(s1, src, var->regoff);
756 M_TINTMOVE(var->type, s1, var->regoff);
760 case ICMD_FSTORE: /* ..., value ==> ... */
761 case ICMD_DSTORE: /* op1 = local variable */
763 if ((src->varkind == LOCALVAR) &&
764 (src->varnum == iptr->op1))
766 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
767 if (var->flags & INMEMORY) {
768 var_to_reg_flt(s1, src, REG_FTMP1);
769 if (var->type == TYPE_DBL)
770 M_DST(s1, REG_SP, 4 * var->regoff);
772 M_FST(s1, REG_SP, 4 * var->regoff);
774 var_to_reg_flt(s1, src, var->regoff);
775 M_FLTMOVE(s1, var->regoff);
780 /* pop/dup/swap operations ********************************************/
782 /* attention: double and longs are only one entry in CACAO ICMDs */
784 case ICMD_POP: /* ..., value ==> ... */
785 case ICMD_POP2: /* ..., value, value ==> ... */
788 case ICMD_DUP: /* ..., a ==> ..., a, a */
789 M_COPY(src, iptr->dst);
792 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
794 M_COPY(src, iptr->dst);
795 M_COPY(src->prev, iptr->dst->prev);
796 M_COPY(iptr->dst, iptr->dst->prev->prev);
799 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
801 M_COPY(src, iptr->dst);
802 M_COPY(src->prev, iptr->dst->prev);
803 M_COPY(src->prev->prev, iptr->dst->prev->prev);
804 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
807 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
809 M_COPY(src, iptr->dst);
810 M_COPY(src->prev, iptr->dst->prev);
813 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
815 M_COPY(src, iptr->dst);
816 M_COPY(src->prev, iptr->dst->prev);
817 M_COPY(src->prev->prev, iptr->dst->prev->prev);
818 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
819 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
822 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
824 M_COPY(src, iptr->dst);
825 M_COPY(src->prev, iptr->dst->prev);
826 M_COPY(src->prev->prev, iptr->dst->prev->prev);
827 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
828 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
829 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
832 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
834 M_COPY(src, iptr->dst->prev);
835 M_COPY(src->prev, iptr->dst);
839 /* integer operations *************************************************/
841 case ICMD_INEG: /* ..., value ==> ..., - value */
843 var_to_reg_int(s1, src, REG_ITMP1);
844 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
846 store_reg_to_var_int(iptr->dst, d);
849 case ICMD_LNEG: /* ..., value ==> ..., - value */
851 var_to_reg_int(s1, src, REG_ITMP1);
852 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
853 M_SUBFIC(rd->secondregs[s1], 0, rd->secondregs[d]);
855 store_reg_to_var_int(iptr->dst, d);
858 case ICMD_I2L: /* ..., value ==> ..., value */
860 var_to_reg_int(s1, src, REG_ITMP2);
861 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
862 M_INTMOVE(s1, rd->secondregs[d]);
863 M_SRA_IMM(rd->secondregs[d], 31, d);
864 store_reg_to_var_int(iptr->dst, d);
867 case ICMD_L2I: /* ..., value ==> ..., value */
869 var_to_reg_int0(s1, src, REG_ITMP2, 0, 1);
870 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
872 store_reg_to_var_int(iptr->dst, d);
875 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
877 var_to_reg_int(s1, src, REG_ITMP1);
878 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
880 store_reg_to_var_int(iptr->dst, d);
883 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
885 var_to_reg_int(s1, src, REG_ITMP1);
886 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
888 store_reg_to_var_int(iptr->dst, d);
891 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
893 var_to_reg_int(s1, src, REG_ITMP1);
894 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
896 store_reg_to_var_int(iptr->dst, d);
900 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
902 var_to_reg_int(s1, src->prev, REG_ITMP1);
903 var_to_reg_int(s2, src, REG_ITMP2);
904 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
906 store_reg_to_var_int(iptr->dst, d);
909 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
910 /* val.i = constant */
912 var_to_reg_int(s1, src, REG_ITMP1);
913 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
914 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
915 M_IADD_IMM(s1, iptr->val.i, d);
918 ICONST(REG_ITMP2, iptr->val.i);
919 M_IADD(s1, REG_ITMP2, d);
921 store_reg_to_var_int(iptr->dst, d);
924 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
926 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
927 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
928 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
929 M_ADDC(s1, s2, rd->secondregs[d]);
930 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
931 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
933 store_reg_to_var_int(iptr->dst, d);
936 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
937 /* val.l = constant */
939 s3 = iptr->val.l & 0xffffffff;
940 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
941 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
942 if ((s3 >= -32768) && (s3 <= 32767)) {
943 M_ADDIC(s1, s3, rd->secondregs[d]);
946 ICONST(REG_ITMP2, s3);
947 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
949 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
950 s3 = iptr->val.l >> 32;
956 ICONST(REG_ITMP3, s3);
957 M_ADDE(s1, REG_ITMP3, d);
959 store_reg_to_var_int(iptr->dst, d);
962 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
964 var_to_reg_int(s1, src->prev, REG_ITMP1);
965 var_to_reg_int(s2, src, REG_ITMP2);
966 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
968 store_reg_to_var_int(iptr->dst, d);
971 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
972 /* val.i = constant */
974 var_to_reg_int(s1, src, REG_ITMP1);
975 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
976 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
977 M_IADD_IMM(s1, -iptr->val.i, d);
980 ICONST(REG_ITMP2, -iptr->val.i);
981 M_IADD(s1, REG_ITMP2, d);
983 store_reg_to_var_int(iptr->dst, d);
986 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
988 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
989 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
990 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
991 M_SUBC(s1, s2, rd->secondregs[d]);
992 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
993 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
995 store_reg_to_var_int(iptr->dst, d);
998 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
999 /* val.l = constant */
1001 s3 = (-iptr->val.l) & 0xffffffff;
1002 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1003 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1004 if ((s3 >= -32768) && (s3 <= 32767)) {
1005 M_ADDIC(s1, s3, rd->secondregs[d]);
1008 ICONST(REG_ITMP2, s3);
1009 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
1011 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1012 s3 = (-iptr->val.l) >> 32;
1018 ICONST(REG_ITMP3, s3);
1019 M_ADDE(s1, REG_ITMP3, d);
1021 store_reg_to_var_int(iptr->dst, d);
1024 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1025 var_to_reg_int(s1, src->prev, REG_ITMP1);
1026 var_to_reg_int(s2, src, REG_ITMP2);
1027 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1029 store_reg_to_var_int(iptr->dst, d);
1032 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1033 var_to_reg_int(s1, src->prev, REG_ITMP1);
1034 var_to_reg_int(s2, src, REG_ITMP2);
1035 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1039 store_reg_to_var_int(iptr->dst, d);
1042 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1044 var_to_reg_int(s1, src->prev, REG_ITMP1);
1045 var_to_reg_int(s2, src, REG_ITMP2);
1046 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1048 store_reg_to_var_int(iptr->dst, d);
1051 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1052 /* val.i = constant */
1054 var_to_reg_int(s1, src, REG_ITMP1);
1055 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1056 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1057 M_IMUL_IMM(s1, iptr->val.i, d);
1060 ICONST(REG_ITMP2, iptr->val.i);
1061 M_IMUL(s1, REG_ITMP2, d);
1063 store_reg_to_var_int(iptr->dst, d);
1066 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1068 var_to_reg_int(s1, src, REG_ITMP1);
1069 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1070 M_SRA_IMM(s1, iptr->val.i, d);
1072 store_reg_to_var_int(iptr->dst, d);
1075 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1077 var_to_reg_int(s1, src->prev, REG_ITMP1);
1078 var_to_reg_int(s2, src, REG_ITMP2);
1079 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1080 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1081 M_SLL(s1, REG_ITMP3, d);
1082 store_reg_to_var_int(iptr->dst, d);
1085 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1086 /* val.i = constant */
1088 var_to_reg_int(s1, src, REG_ITMP1);
1089 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1090 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1091 store_reg_to_var_int(iptr->dst, d);
1094 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1096 var_to_reg_int(s1, src->prev, REG_ITMP1);
1097 var_to_reg_int(s2, src, REG_ITMP2);
1098 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1099 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1100 M_SRA(s1, REG_ITMP3, d);
1101 store_reg_to_var_int(iptr->dst, d);
1104 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1105 /* val.i = constant */
1107 var_to_reg_int(s1, src, REG_ITMP1);
1108 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1109 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1110 store_reg_to_var_int(iptr->dst, d);
1113 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1115 var_to_reg_int(s1, src->prev, REG_ITMP1);
1116 var_to_reg_int(s2, src, REG_ITMP2);
1117 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1118 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1119 M_SRL(s1, REG_ITMP2, d);
1120 store_reg_to_var_int(iptr->dst, d);
1123 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1124 /* val.i = constant */
1126 var_to_reg_int(s1, src, REG_ITMP1);
1127 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1128 if (iptr->val.i & 0x1f)
1129 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1132 store_reg_to_var_int(iptr->dst, d);
1135 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1137 var_to_reg_int(s1, src->prev, REG_ITMP1);
1138 var_to_reg_int(s2, src, REG_ITMP2);
1139 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1141 store_reg_to_var_int(iptr->dst, d);
1144 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1145 /* val.i = constant */
1147 var_to_reg_int(s1, src, REG_ITMP1);
1148 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1149 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1150 M_AND_IMM(s1, iptr->val.i, d);
1153 else if (iptr->val.i == 0xffffff) {
1154 M_RLWINM(s1, 0, 8, 31, d);
1158 ICONST(REG_ITMP2, iptr->val.i);
1159 M_AND(s1, REG_ITMP2, d);
1161 store_reg_to_var_int(iptr->dst, d);
1164 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1166 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1167 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1168 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1169 M_AND(s1, s2, rd->secondregs[d]);
1170 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1171 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1173 store_reg_to_var_int(iptr->dst, d);
1176 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1177 /* val.l = constant */
1179 s3 = iptr->val.l & 0xffffffff;
1180 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1181 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1182 if ((s3 >= 0) && (s3 <= 65535)) {
1183 M_AND_IMM(s1, s3, rd->secondregs[d]);
1186 ICONST(REG_ITMP2, s3);
1187 M_AND(s1, REG_ITMP2, rd->secondregs[d]);
1189 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1190 s3 = iptr->val.l >> 32;
1191 if ((s3 >= 0) && (s3 <= 65535)) {
1192 M_AND_IMM(s1, s3, d);
1195 ICONST(REG_ITMP3, s3);
1196 M_AND(s1, REG_ITMP3, d);
1198 store_reg_to_var_int(iptr->dst, d);
1201 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1202 /* val.i = constant */
1204 var_to_reg_int(s1, src, REG_ITMP1);
1205 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1206 M_MOV(s1, REG_ITMP2);
1208 M_BGE(1 + 2*(iptr->val.i >= 32768));
1209 if (iptr->val.i >= 32768) {
1210 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1211 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1212 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1215 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1217 int b=0, m = iptr->val.i;
1220 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1222 M_ISUB(s1, REG_ITMP2, d);
1223 store_reg_to_var_int(iptr->dst, d);
1226 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1228 var_to_reg_int(s1, src->prev, REG_ITMP1);
1229 var_to_reg_int(s2, src, REG_ITMP2);
1230 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1232 store_reg_to_var_int(iptr->dst, d);
1235 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1236 /* val.i = constant */
1238 var_to_reg_int(s1, src, REG_ITMP1);
1239 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1240 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1241 M_OR_IMM(s1, iptr->val.i, d);
1244 ICONST(REG_ITMP2, iptr->val.i);
1245 M_OR(s1, REG_ITMP2, d);
1247 store_reg_to_var_int(iptr->dst, d);
1250 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1252 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1253 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1254 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1255 M_OR(s1, s2, rd->secondregs[d]);
1256 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1257 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1259 store_reg_to_var_int(iptr->dst, d);
1262 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1263 /* val.l = constant */
1265 s3 = iptr->val.l & 0xffffffff;
1266 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1267 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1268 if ((s3 >= 0) && (s3 <= 65535)) {
1269 M_OR_IMM(s1, s3, rd->secondregs[d]);
1272 ICONST(REG_ITMP2, s3);
1273 M_OR(s1, REG_ITMP2, rd->secondregs[d]);
1275 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1276 s3 = iptr->val.l >> 32;
1277 if ((s3 >= 0) && (s3 <= 65535)) {
1278 M_OR_IMM(s1, s3, d);
1281 ICONST(REG_ITMP3, s3);
1282 M_OR(s1, REG_ITMP3, d);
1284 store_reg_to_var_int(iptr->dst, d);
1287 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1289 var_to_reg_int(s1, src->prev, REG_ITMP1);
1290 var_to_reg_int(s2, src, REG_ITMP2);
1291 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1293 store_reg_to_var_int(iptr->dst, d);
1296 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1297 /* val.i = constant */
1299 var_to_reg_int(s1, src, REG_ITMP1);
1300 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1301 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1302 M_XOR_IMM(s1, iptr->val.i, d);
1305 ICONST(REG_ITMP2, iptr->val.i);
1306 M_XOR(s1, REG_ITMP2, d);
1308 store_reg_to_var_int(iptr->dst, d);
1311 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1313 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1314 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1315 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1316 M_XOR(s1, s2, rd->secondregs[d]);
1317 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1318 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1320 store_reg_to_var_int(iptr->dst, d);
1323 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1324 /* val.l = constant */
1326 s3 = iptr->val.l & 0xffffffff;
1327 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1328 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1329 if ((s3 >= 0) && (s3 <= 65535)) {
1330 M_XOR_IMM(s1, s3, rd->secondregs[d]);
1333 ICONST(REG_ITMP2, s3);
1334 M_XOR(s1, REG_ITMP2, rd->secondregs[d]);
1336 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1337 s3 = iptr->val.l >> 32;
1338 if ((s3 >= 0) && (s3 <= 65535)) {
1339 M_XOR_IMM(s1, s3, d);
1342 ICONST(REG_ITMP3, s3);
1343 M_XOR(s1, REG_ITMP3, d);
1345 store_reg_to_var_int(iptr->dst, d);
1348 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1350 var_to_reg_int0(s1, src->prev, REG_ITMP3, 1, 0);
1351 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
1352 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1355 (d==s1 || d==s2 || d==rd->secondregs[s1] || d==rd->secondregs[s2]);
1356 int dreg = tempreg ? REG_ITMP1 : d;
1358 M_IADD_IMM(REG_ZERO, 1, dreg);
1363 var_to_reg_int0(s1, src->prev, REG_ITMP3, 0, 1);
1364 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1368 M_IADD_IMM(dreg, -1, dreg);
1369 M_IADD_IMM(dreg, -1, dreg);
1370 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1371 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1374 store_reg_to_var_int(iptr->dst, d);
1377 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1378 /* op1 = variable, val.i = constant */
1380 var = &(rd->locals[iptr->op1][TYPE_INT]);
1381 if (var->flags & INMEMORY) {
1383 M_ILD(s1, REG_SP, 4 * var->regoff);
1392 M_ADDIS(s1, m>>16, s1);
1394 M_IADD_IMM(s1, m&0xffff, s1);
1396 if (var->flags & INMEMORY)
1397 M_IST(s1, REG_SP, 4 * var->regoff);
1401 /* floating operations ************************************************/
1403 case ICMD_FNEG: /* ..., value ==> ..., - value */
1405 var_to_reg_flt(s1, src, REG_FTMP1);
1406 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1408 store_reg_to_var_flt(iptr->dst, d);
1411 case ICMD_DNEG: /* ..., value ==> ..., - value */
1413 var_to_reg_flt(s1, src, REG_FTMP1);
1414 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1416 store_reg_to_var_flt(iptr->dst, d);
1419 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1421 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1422 var_to_reg_flt(s2, src, REG_FTMP2);
1423 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1425 store_reg_to_var_flt(iptr->dst, d);
1428 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1430 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1431 var_to_reg_flt(s2, src, REG_FTMP2);
1432 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1434 store_reg_to_var_flt(iptr->dst, d);
1437 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1439 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1440 var_to_reg_flt(s2, src, REG_FTMP2);
1441 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1443 store_reg_to_var_flt(iptr->dst, d);
1446 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1448 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1449 var_to_reg_flt(s2, src, REG_FTMP2);
1450 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1452 store_reg_to_var_flt(iptr->dst, d);
1455 case ICMD_FMUL: /* ..., 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_DMUL: /* ..., 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_FDIV: /* ..., 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_DDIV: /* ..., 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_F2I: /* ..., value ==> ..., (int) value */
1493 var_to_reg_flt(s1, src, REG_FTMP1);
1494 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1496 a = dseg_addfloat(cd, 0.0);
1497 M_FLD(REG_FTMP2, REG_PV, a);
1498 M_FCMPU(s1, REG_FTMP2);
1500 a = dseg_adds4(cd, 0);
1501 M_CVTDL_C(s1, REG_FTMP1);
1502 M_LDA (REG_ITMP1, REG_PV, a);
1503 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1504 M_ILD (d, REG_PV, a);
1505 store_reg_to_var_int(iptr->dst, d);
1508 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1510 var_to_reg_flt(s1, src, REG_FTMP1);
1511 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1513 store_reg_to_var_flt(iptr->dst, d);
1516 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1518 var_to_reg_flt(s1, src, REG_FTMP1);
1519 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1521 store_reg_to_var_flt(iptr->dst, d);
1524 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1526 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1527 var_to_reg_flt(s2, src, REG_FTMP2);
1528 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1530 M_IADD_IMM(0, -1, d);
1533 M_IADD_IMM(0, 0, d);
1535 M_IADD_IMM(0, 1, d);
1536 store_reg_to_var_int(iptr->dst, d);
1539 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1541 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1542 var_to_reg_flt(s2, src, REG_FTMP2);
1543 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1545 M_IADD_IMM(0, 1, d);
1548 M_IADD_IMM(0, 0, d);
1550 M_IADD_IMM(0, -1, d);
1551 store_reg_to_var_int(iptr->dst, d);
1555 /* memory operations **************************************************/
1557 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1559 var_to_reg_int(s1, src, REG_ITMP1);
1560 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1561 gen_nullptr_check(s1);
1562 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1563 store_reg_to_var_int(iptr->dst, d);
1566 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1568 var_to_reg_int(s1, src->prev, REG_ITMP1);
1569 var_to_reg_int(s2, src, REG_ITMP2);
1570 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1571 if (iptr->op1 == 0) {
1572 gen_nullptr_check(s1);
1575 M_SLL_IMM(s2, 2, REG_ITMP2);
1576 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1577 M_LWZX(d, s1, REG_ITMP2);
1578 store_reg_to_var_int(iptr->dst, d);
1581 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1583 var_to_reg_int(s1, src->prev, REG_ITMP1);
1584 var_to_reg_int(s2, src, REG_ITMP2);
1585 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1586 if (iptr->op1 == 0) {
1587 gen_nullptr_check(s1);
1590 M_SLL_IMM(s2, 3, REG_ITMP2);
1591 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1592 M_ILD(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
1593 M_ILD(rd->secondregs[d], REG_ITMP2, OFFSET(java_longarray, data[0])+4);
1594 store_reg_to_var_int(iptr->dst, d);
1597 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1599 var_to_reg_int(s1, src->prev, REG_ITMP1);
1600 var_to_reg_int(s2, src, REG_ITMP2);
1601 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1602 if (iptr->op1 == 0) {
1603 gen_nullptr_check(s1);
1606 M_SLL_IMM(s2, 2, REG_ITMP2);
1607 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1608 M_LWZX(d, s1, REG_ITMP2);
1609 store_reg_to_var_int(iptr->dst, d);
1612 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1614 var_to_reg_int(s1, src->prev, REG_ITMP1);
1615 var_to_reg_int(s2, src, REG_ITMP2);
1616 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1617 if (iptr->op1 == 0) {
1618 gen_nullptr_check(s1);
1621 M_SLL_IMM(s2, 2, REG_ITMP2);
1622 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1623 M_LFSX(d, s1, REG_ITMP2);
1624 store_reg_to_var_flt(iptr->dst, d);
1627 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1629 var_to_reg_int(s1, src->prev, REG_ITMP1);
1630 var_to_reg_int(s2, src, REG_ITMP2);
1631 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1632 if (iptr->op1 == 0) {
1633 gen_nullptr_check(s1);
1636 M_SLL_IMM(s2, 3, REG_ITMP2);
1637 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1638 M_LFDX(d, s1, REG_ITMP2);
1639 store_reg_to_var_flt(iptr->dst, d);
1642 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1644 var_to_reg_int(s1, src->prev, REG_ITMP1);
1645 var_to_reg_int(s2, src, REG_ITMP2);
1646 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1647 if (iptr->op1 == 0) {
1648 gen_nullptr_check(s1);
1651 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1652 M_LBZX(d, s1, REG_ITMP2);
1654 store_reg_to_var_int(iptr->dst, d);
1657 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1659 var_to_reg_int(s1, src->prev, REG_ITMP1);
1660 var_to_reg_int(s2, src, REG_ITMP2);
1661 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1662 if (iptr->op1 == 0) {
1663 gen_nullptr_check(s1);
1666 M_SLL_IMM(s2, 1, REG_ITMP2);
1667 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1668 M_LHAX(d, s1, REG_ITMP2);
1669 store_reg_to_var_int(iptr->dst, d);
1672 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1674 var_to_reg_int(s1, src->prev, REG_ITMP1);
1675 var_to_reg_int(s2, src, REG_ITMP2);
1676 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1677 if (iptr->op1 == 0) {
1678 gen_nullptr_check(s1);
1681 M_SLL_IMM(s2, 1, REG_ITMP2);
1682 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1683 M_LHZX(d, s1, REG_ITMP2);
1684 store_reg_to_var_int(iptr->dst, d);
1687 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1689 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1690 var_to_reg_int(s2, src->prev, REG_ITMP2);
1691 if (iptr->op1 == 0) {
1692 gen_nullptr_check(s1);
1695 var_to_reg_int0(s3, src, REG_ITMP3, 1, 0);
1696 M_SLL_IMM(s2, 3, REG_ITMP2);
1697 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1698 M_STWX(s3, s1, REG_ITMP2);
1699 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1700 var_to_reg_int0(s3, src, REG_ITMP3, 0, 1);
1701 M_STWX(s3, s1, REG_ITMP2);
1704 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1706 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1707 var_to_reg_int(s2, src->prev, REG_ITMP2);
1708 if (iptr->op1 == 0) {
1709 gen_nullptr_check(s1);
1712 var_to_reg_int(s3, src, REG_ITMP3);
1713 M_SLL_IMM(s2, 2, REG_ITMP2);
1714 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1715 M_STWX(s3, s1, REG_ITMP2);
1718 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1720 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1721 var_to_reg_int(s2, src->prev, REG_ITMP2);
1722 if (iptr->op1 == 0) {
1723 gen_nullptr_check(s1);
1726 var_to_reg_flt(s3, src, REG_FTMP3);
1727 M_SLL_IMM(s2, 2, REG_ITMP2);
1728 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1729 M_STFSX(s3, s1, REG_ITMP2);
1732 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1734 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1735 var_to_reg_int(s2, src->prev, REG_ITMP2);
1736 if (iptr->op1 == 0) {
1737 gen_nullptr_check(s1);
1740 var_to_reg_flt(s3, src, REG_FTMP3);
1741 M_SLL_IMM(s2, 3, REG_ITMP2);
1742 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1743 M_STFDX(s3, s1, REG_ITMP2);
1746 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1748 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1749 var_to_reg_int(s2, src->prev, REG_ITMP2);
1750 if (iptr->op1 == 0) {
1751 gen_nullptr_check(s1);
1754 var_to_reg_int(s3, src, REG_ITMP3);
1755 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1756 M_STBX(s3, s1, REG_ITMP2);
1759 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1761 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1762 var_to_reg_int(s2, src->prev, REG_ITMP2);
1763 if (iptr->op1 == 0) {
1764 gen_nullptr_check(s1);
1767 var_to_reg_int(s3, src, REG_ITMP3);
1768 M_SLL_IMM(s2, 1, REG_ITMP2);
1769 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1770 M_STHX(s3, s1, REG_ITMP2);
1773 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1775 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1776 var_to_reg_int(s2, src->prev, REG_ITMP2);
1777 if (iptr->op1 == 0) {
1778 gen_nullptr_check(s1);
1781 var_to_reg_int(s3, src, REG_ITMP3);
1782 M_SLL_IMM(s2, 1, REG_ITMP2);
1783 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1784 M_STHX(s3, s1, REG_ITMP2);
1787 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1788 /* op1 = type, val.a = field address */
1790 /* if class isn't yet initialized, do it */
1791 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1792 /* call helper function which patches this code */
1793 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1794 M_ALD(REG_ITMP1, REG_PV, a);
1795 a = dseg_addaddress(cd, asm_check_clinit);
1796 M_ALD(REG_PV, REG_PV, a);
1801 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1803 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1805 s4 ml = -s1, mh = 0;
1806 while (ml < -32768) { ml += 65536; mh--; }
1807 M_LDA(REG_PV, REG_ITMP1, ml);
1808 M_LDAH(REG_PV, REG_PV, mh);
1812 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1813 M_ALD(REG_ITMP1, REG_PV, a);
1814 switch (iptr->op1) {
1816 var_to_reg_int(s2, src, REG_ITMP2);
1817 M_IST(s2, REG_ITMP1, 0);
1820 var_to_reg_int(s2, src, REG_ITMP3);
1821 M_IST(s2, REG_ITMP1, 0);
1822 M_IST(rd->secondregs[s2], REG_ITMP1, 4);
1825 var_to_reg_int(s2, src, REG_ITMP2);
1826 M_AST(s2, REG_ITMP1, 0);
1829 var_to_reg_flt(s2, src, REG_FTMP2);
1830 M_FST(s2, REG_ITMP1, 0);
1833 var_to_reg_flt(s2, src, REG_FTMP2);
1834 M_DST(s2, REG_ITMP1, 0);
1836 default: panic ("internal error");
1840 case ICMD_GETSTATIC: /* ... ==> ..., value */
1841 /* op1 = type, val.a = field address */
1843 /* if class isn't yet initialized, do it */
1844 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1845 /* call helper function which patches this code */
1846 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1847 M_ALD(REG_ITMP1, REG_PV, a);
1848 a = dseg_addaddress(cd, asm_check_clinit);
1849 M_ALD(REG_PV, REG_PV, a);
1854 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1856 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1858 s4 ml = -s1, mh = 0;
1859 while (ml < -32768) { ml += 65536; mh--; }
1860 M_LDA(REG_PV, REG_ITMP1, ml);
1861 M_LDAH(REG_PV, REG_PV, mh);
1865 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1866 M_ALD(REG_ITMP1, REG_PV, a);
1867 switch (iptr->op1) {
1869 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1870 M_ILD(d, REG_ITMP1, 0);
1871 store_reg_to_var_int(iptr->dst, d);
1874 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1875 M_ILD(d, REG_ITMP1, 0);
1876 M_ILD(rd->secondregs[d], REG_ITMP1, 4);
1877 store_reg_to_var_int(iptr->dst, d);
1880 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1881 M_ALD(d, REG_ITMP1, 0);
1882 store_reg_to_var_int(iptr->dst, d);
1885 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1886 M_FLD(d, REG_ITMP1, 0);
1887 store_reg_to_var_flt(iptr->dst, d);
1890 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1891 M_DLD(d, REG_ITMP1, 0);
1892 store_reg_to_var_flt(iptr->dst, d);
1894 default: panic ("internal error");
1899 case ICMD_PUTFIELD: /* ..., value ==> ... */
1900 /* op1 = type, val.i = field offset */
1902 a = ((fieldinfo *)(iptr->val.a))->offset;
1903 switch (iptr->op1) {
1905 var_to_reg_int(s1, src->prev, REG_ITMP1);
1906 var_to_reg_int(s2, src, REG_ITMP2);
1907 gen_nullptr_check(s1);
1911 var_to_reg_int(s1, src->prev, REG_ITMP1);
1912 var_to_reg_int(s2, src, REG_ITMP3);
1913 gen_nullptr_check(s1);
1915 M_IST(rd->secondregs[s2], s1, a+4);
1918 var_to_reg_int(s1, src->prev, REG_ITMP1);
1919 var_to_reg_int(s2, src, REG_ITMP2);
1920 gen_nullptr_check(s1);
1924 var_to_reg_int(s1, src->prev, REG_ITMP1);
1925 var_to_reg_flt(s2, src, REG_FTMP2);
1926 gen_nullptr_check(s1);
1930 var_to_reg_int(s1, src->prev, REG_ITMP1);
1931 var_to_reg_flt(s2, src, REG_FTMP2);
1932 gen_nullptr_check(s1);
1935 default: panic ("internal error");
1939 case ICMD_GETFIELD: /* ... ==> ..., value */
1940 /* op1 = type, val.i = field offset */
1942 a = ((fieldinfo *)(iptr->val.a))->offset;
1943 switch (iptr->op1) {
1945 var_to_reg_int(s1, src, REG_ITMP1);
1946 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1947 gen_nullptr_check(s1);
1949 store_reg_to_var_int(iptr->dst, d);
1952 var_to_reg_int(s1, src, REG_ITMP1);
1953 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1954 gen_nullptr_check(s1);
1956 M_ILD(rd->secondregs[d], s1, a+4);
1957 store_reg_to_var_int(iptr->dst, d);
1960 var_to_reg_int(s1, src, REG_ITMP1);
1961 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1962 gen_nullptr_check(s1);
1964 store_reg_to_var_int(iptr->dst, d);
1967 var_to_reg_int(s1, src, REG_ITMP1);
1968 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1969 gen_nullptr_check(s1);
1971 store_reg_to_var_flt(iptr->dst, d);
1974 var_to_reg_int(s1, src, REG_ITMP1);
1975 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1976 gen_nullptr_check(s1);
1978 store_reg_to_var_flt(iptr->dst, d);
1980 default: panic ("internal error");
1985 /* branch operations **************************************************/
1987 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1989 a = dseg_addaddress(cd, asm_handle_exception);
1990 M_ALD(REG_ITMP2, REG_PV, a);
1992 var_to_reg_int(s1, src, REG_ITMP1);
1993 M_INTMOVE(s1, REG_ITMP1_XPTR);
1995 if (m->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
1996 M_BL(0); /* get current PC */
1997 M_MFLR(REG_ITMP2_XPC);
1998 if (m->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
1999 M_RTS; /* jump to CTR */
2004 case ICMD_GOTO: /* ... ==> ... */
2005 /* op1 = target JavaVM pc */
2007 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2011 case ICMD_JSR: /* ... ==> ... */
2012 /* op1 = target JavaVM pc */
2014 if (m->isleafmethod) M_MFLR(REG_ITMP2);
2017 M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
2018 if (m->isleafmethod) M_MTLR(REG_ITMP2);
2020 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2023 case ICMD_RET: /* ... ==> ... */
2024 /* op1 = local variable */
2026 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2027 if (var->flags & INMEMORY) {
2028 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
2032 M_MTCTR(var->regoff);
2037 case ICMD_IFNULL: /* ..., value ==> ... */
2038 /* op1 = target JavaVM pc */
2040 var_to_reg_int(s1, src, REG_ITMP1);
2043 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2046 case ICMD_IFNONNULL: /* ..., value ==> ... */
2047 /* op1 = target JavaVM pc */
2049 var_to_reg_int(s1, src, REG_ITMP1);
2052 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2060 case ICMD_IFEQ: /* ..., value ==> ... */
2061 /* op1 = target JavaVM pc, val.i = constant */
2063 var_to_reg_int(s1, src, REG_ITMP1);
2064 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2065 M_CMPI(s1, iptr->val.i);
2068 ICONST(REG_ITMP2, iptr->val.i);
2069 M_CMP(s1, REG_ITMP2);
2092 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2096 case ICMD_IF_LEQ: /* ..., value ==> ... */
2097 /* op1 = target JavaVM pc, val.l = constant */
2099 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2100 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2101 if (iptr->val.l == 0) {
2102 M_OR(s1, s2, REG_ITMP3);
2103 M_CMPI(REG_ITMP3, 0);
2105 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2106 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2108 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2111 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2112 M_CMP(s2, REG_ITMP3);
2114 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2115 M_CMP(s1, REG_ITMP3)
2118 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2121 case ICMD_IF_LLT: /* ..., value ==> ... */
2122 /* op1 = target JavaVM pc, val.l = constant */
2123 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2124 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2125 /* if (iptr->val.l == 0) { */
2126 /* M_OR(s1, s2, REG_ITMP3); */
2127 /* M_CMPI(REG_ITMP3, 0); */
2130 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2131 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2133 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2135 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2138 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2139 M_CMP(s2, REG_ITMP3);
2141 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2143 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2144 M_CMP(s1, REG_ITMP3)
2147 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2150 case ICMD_IF_LLE: /* ..., value ==> ... */
2151 /* op1 = target JavaVM pc, val.l = constant */
2153 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2154 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2155 /* if (iptr->val.l == 0) { */
2156 /* M_OR(s1, s2, REG_ITMP3); */
2157 /* M_CMPI(REG_ITMP3, 0); */
2160 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2161 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2163 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2165 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2168 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2169 M_CMP(s2, REG_ITMP3);
2171 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2173 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2174 M_CMP(s1, REG_ITMP3)
2177 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2180 case ICMD_IF_LNE: /* ..., value ==> ... */
2181 /* op1 = target JavaVM pc, val.l = constant */
2183 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2184 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2185 if (iptr->val.l == 0) {
2186 M_OR(s1, s2, REG_ITMP3);
2187 M_CMPI(REG_ITMP3, 0);
2189 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2190 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2192 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2195 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2196 M_CMP(s2, REG_ITMP3);
2198 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2199 M_CMP(s1, REG_ITMP3)
2202 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2205 case ICMD_IF_LGT: /* ..., value ==> ... */
2206 /* op1 = target JavaVM pc, val.l = constant */
2208 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2209 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2210 /* if (iptr->val.l == 0) { */
2211 /* M_OR(s1, s2, REG_ITMP3); */
2212 /* M_CMPI(REG_ITMP3, 0); */
2215 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2216 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2218 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2220 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2223 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2224 M_CMP(s2, REG_ITMP3);
2226 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2228 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2229 M_CMP(s1, REG_ITMP3)
2232 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2235 case ICMD_IF_LGE: /* ..., value ==> ... */
2236 /* op1 = target JavaVM pc, val.l = constant */
2237 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2238 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2239 /* if (iptr->val.l == 0) { */
2240 /* M_OR(s1, s2, REG_ITMP3); */
2241 /* M_CMPI(REG_ITMP3, 0); */
2244 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2245 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2247 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2249 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2252 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2253 M_CMP(s2, REG_ITMP3);
2255 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2257 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2258 M_CMP(s1, REG_ITMP3)
2261 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2265 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2266 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2267 case ICMD_IF_ACMPEQ:
2269 var_to_reg_int(s1, src->prev, REG_ITMP1);
2270 var_to_reg_int(s2, src, REG_ITMP2);
2273 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2276 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2277 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2278 case ICMD_IF_ACMPNE:
2280 var_to_reg_int(s1, src->prev, REG_ITMP1);
2281 var_to_reg_int(s2, src, REG_ITMP2);
2284 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2287 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2288 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2290 var_to_reg_int(s1, src->prev, REG_ITMP1);
2291 var_to_reg_int(s2, src, REG_ITMP2);
2294 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2297 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2298 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2300 var_to_reg_int(s1, src->prev, REG_ITMP1);
2301 var_to_reg_int(s2, src, REG_ITMP2);
2304 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2307 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2308 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2310 var_to_reg_int(s1, src->prev, REG_ITMP1);
2311 var_to_reg_int(s2, src, REG_ITMP2);
2314 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2317 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2318 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2320 var_to_reg_int(s1, src->prev, REG_ITMP1);
2321 var_to_reg_int(s2, src, REG_ITMP2);
2324 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2327 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2331 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2334 case ICMD_RETURN: /* ... ==> ... */
2336 #if defined(USE_THREADS)
2337 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2338 a = dseg_addaddress(cd, (void *) (builtin_monitorexit));
2339 M_ALD(REG_ITMP3, REG_PV, a);
2341 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
2345 switch (iptr->opc) {
2349 var_to_reg_int(s1, src, REG_RESULT);
2350 M_TINTMOVE(src->type, s1, REG_RESULT);
2351 goto nowperformreturn;
2355 var_to_reg_flt(s1, src, REG_FRESULT);
2356 M_FLTMOVE(s1, REG_FRESULT);
2357 goto nowperformreturn;
2364 p = parentargs_base;
2366 /* restore return address */
2368 if (!m->isleafmethod) {
2369 M_ALD(REG_ITMP3, REG_SP, 4 * p + 8);
2373 /* restore saved registers */
2375 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2376 p--; M_ILD(rd->savintregs[i], REG_SP, 4 * p);
2378 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2379 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, 4 * p);
2382 /* deallocate stack */
2384 if (parentargs_base) {
2385 M_LDA(REG_SP, REG_SP, parentargs_base*4);
2388 /* call trace function */
2392 M_LDA(REG_SP, REG_SP, -10 * 8);
2393 M_DST(REG_FRESULT, REG_SP, 48+0);
2394 M_IST(REG_RESULT, REG_SP, 48+8);
2395 M_AST(REG_ITMP3, REG_SP, 48+12);
2396 M_IST(REG_RESULT2, REG_SP, 48+16);
2397 a = dseg_addaddress(cd, m);
2399 /* keep this order */
2400 switch (iptr->opc) {
2403 M_MOV(REG_RESULT, rd->argintregs[2]);
2404 M_CLR(rd->argintregs[1]);
2408 M_MOV(REG_RESULT2, rd->argintregs[2]);
2409 M_MOV(REG_RESULT, rd->argintregs[1]);
2412 M_ALD(rd->argintregs[0], REG_PV, a);
2414 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2415 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2416 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2417 M_ALD(REG_ITMP2, REG_PV, a);
2420 M_DLD(REG_FRESULT, REG_SP, 48+0);
2421 M_ILD(REG_RESULT, REG_SP, 48+8);
2422 M_ALD(REG_ITMP3, REG_SP, 48+12);
2423 M_ILD(REG_RESULT2, REG_SP, 48+16);
2424 M_LDA(REG_SP, REG_SP, 10 * 8);
2434 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2439 tptr = (void **) iptr->target;
2441 s4ptr = iptr->val.a;
2442 l = s4ptr[1]; /* low */
2443 i = s4ptr[2]; /* high */
2445 var_to_reg_int(s1, src, REG_ITMP1);
2447 M_INTMOVE(s1, REG_ITMP1);
2448 } else if (l <= 32768) {
2449 M_LDA(REG_ITMP1, s1, -l);
2451 ICONST(REG_ITMP2, l);
2452 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2458 M_CMPUI(REG_ITMP1, i - 1);
2461 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2462 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2464 /* build jump table top down and use address of lowest entry */
2466 /* s4ptr += 3 + i; */
2470 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2471 dseg_addtarget(cd, (basicblock *) tptr[0]);
2476 /* length of dataseg after last dseg_addtarget is used by load */
2478 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2479 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2480 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2487 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2489 s4 i, l, val, *s4ptr;
2492 tptr = (void **) iptr->target;
2494 s4ptr = iptr->val.a;
2495 l = s4ptr[0]; /* default */
2496 i = s4ptr[1]; /* count */
2498 MCODECHECK((i<<2)+8);
2499 var_to_reg_int(s1, src, REG_ITMP1);
2505 if ((val >= -32768) && (val <= 32767)) {
2509 a = dseg_adds4(cd, val);
2510 M_ILD(REG_ITMP2, REG_PV, a);
2511 M_CMP(s1, REG_ITMP2);
2514 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2515 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2519 /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2521 tptr = (void **) iptr->target;
2522 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2529 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2530 /* op1 = return type, val.a = function pointer*/
2534 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2535 /* op1 = return type, val.a = function pointer*/
2539 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2540 /* op1 = return type, val.a = function pointer*/
2544 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2545 /* op1 = arg count, val.a = method pointer */
2547 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2548 /* op1 = arg count, val.a = method pointer */
2550 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2551 /* op1 = arg count, val.a = method pointer */
2553 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2554 /* op1 = arg count, val.a = method pointer */
2562 MCODECHECK((s3 << 1) + 64);
2565 /* copy arguments to registers or stack location */
2567 stackptr srcsave = src;
2571 for (; --s3 >= 0; src = src->prev) {
2572 argsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
2573 if (IS_FLT_DBL_TYPE(src->type))
2577 for (s3 = s3save, src = srcsave; --s3 >= 0; src = src->prev) {
2578 argsize -= IS_2_WORD_TYPE(src->type) ? 2 : 1;
2579 if (IS_FLT_DBL_TYPE(src->type))
2581 if (src->varkind == ARGVAR)
2583 if (IS_INT_LNG_TYPE(src->type)) {
2584 if (argsize < INT_ARG_CNT) {
2585 s1 = rd->argintregs[argsize];
2586 var_to_reg_int(d, src, s1);
2587 if (argsize < INT_ARG_CNT-1) {
2588 M_TINTMOVE(src->type, d, s1);
2592 if (IS_2_WORD_TYPE(src->type))
2593 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2597 var_to_reg_int(d, src, REG_ITMP1);
2598 M_IST(d, REG_SP, 4 * (argsize + 6));
2599 if (IS_2_WORD_TYPE(src->type))
2600 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2604 if (fltcnt < FLT_ARG_CNT) {
2605 s1 = rd->argfltregs[fltcnt];
2606 var_to_reg_flt(d, src, s1);
2610 var_to_reg_flt(d, src, REG_FTMP1);
2611 if (IS_2_WORD_TYPE(src->type))
2612 M_DST(d, REG_SP, 4 * (argsize + 6));
2614 M_FST(d, REG_SP, 4 * (argsize + 6));
2621 switch (iptr->opc) {
2625 a = dseg_addaddress(cd, (void *) lm);
2627 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2629 goto makeactualcall;
2631 case ICMD_INVOKESTATIC:
2632 case ICMD_INVOKESPECIAL:
2633 a = dseg_addaddress(cd, lm->stubroutine);
2635 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
2638 goto makeactualcall;
2640 case ICMD_INVOKEVIRTUAL:
2642 gen_nullptr_check(rd->argintregs[0]);
2643 M_ALD(REG_METHODPTR, rd->argintregs[0],
2644 OFFSET(java_objectheader, vftbl));
2645 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) +
2646 sizeof(methodptr) * lm->vftblindex);
2649 goto makeactualcall;
2651 case ICMD_INVOKEINTERFACE:
2654 gen_nullptr_check(rd->argintregs[0]);
2655 M_ALD(REG_METHODPTR, rd->argintregs[0],
2656 OFFSET(java_objectheader, vftbl));
2657 M_ALD(REG_METHODPTR, REG_METHODPTR,
2658 OFFSET(vftbl_t, interfacetable[0]) -
2659 sizeof(methodptr*) * ci->index);
2660 M_ALD(REG_PV, REG_METHODPTR,
2661 sizeof(methodptr) * (lm - ci->methods));
2664 goto makeactualcall;
2668 error ("Unkown ICMD-Command: %d", iptr->opc);
2677 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2679 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2681 s4 ml = -s1, mh = 0;
2682 while (ml < -32768) { ml += 65536; mh--; }
2683 M_LDA(REG_PV, REG_ITMP1, ml);
2684 M_LDAH(REG_PV, REG_PV, mh);
2687 /* d contains return type */
2689 if (d != TYPE_VOID) {
2690 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2691 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2692 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2693 store_reg_to_var_int(iptr->dst, s1);
2696 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2697 M_FLTMOVE(REG_FRESULT, s1);
2698 store_reg_to_var_flt(iptr->dst, s1);
2705 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2707 /* op1: 0 == array, 1 == class */
2708 /* val.a: (classinfo*) superclass */
2710 /* superclass is an interface:
2712 * return (sub != NULL) &&
2713 * (sub->vftbl->interfacetablelength > super->index) &&
2714 * (sub->vftbl->interfacetable[-super->index] != NULL);
2716 * superclass is a class:
2718 * return ((sub != NULL) && (0
2719 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2720 * super->vftbl->diffvall));
2724 classinfo *super = (classinfo*) iptr->val.a;
2726 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2727 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2729 var_to_reg_int(s1, src, REG_ITMP1);
2730 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2732 M_MOV(s1, REG_ITMP1);
2736 if (iptr->op1) { /* class/interface */
2738 if (super->flags & ACC_INTERFACE) { /* interface */
2740 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2741 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2742 M_LDATST(REG_ITMP2, REG_ITMP2, - super->index);
2744 M_ALD(REG_ITMP1, REG_ITMP1,
2745 OFFSET(vftbl_t, interfacetable[0]) -
2746 super->index * sizeof(methodptr*));
2750 M_IADD_IMM(REG_ZERO, 1, d);
2754 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2755 a = dseg_addaddress(cd, (void*) super->vftbl);
2756 M_ALD(REG_ITMP2, REG_PV, a);
2757 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2758 codegen_threadcritstart(cd, (u1*) mcodeptr - cd->mcodebase);
2760 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2761 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2762 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2763 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2764 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2766 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2767 M_CMPU(REG_ITMP1, REG_ITMP2);
2770 M_IADD_IMM(REG_ZERO, 1, d);
2774 panic ("internal error: no inlined array instanceof");
2776 store_reg_to_var_int(iptr->dst, d);
2779 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2781 /* op1: 0 == array, 1 == class */
2782 /* val.a: (classinfo*) superclass */
2784 /* superclass is an interface:
2786 * OK if ((sub == NULL) ||
2787 * (sub->vftbl->interfacetablelength > super->index) &&
2788 * (sub->vftbl->interfacetable[-super->index] != NULL));
2790 * superclass is a class:
2792 * OK if ((sub == NULL) || (0
2793 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2794 * super->vftbl->diffvall));
2798 classinfo *super = (classinfo*) iptr->val.a;
2800 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2801 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2803 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2804 var_to_reg_int(s1, src, d);
2805 if (iptr->op1) { /* class/interface */
2807 if (super->flags & ACC_INTERFACE) { /* interface */
2809 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2810 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2811 M_LDATST(REG_ITMP3, REG_ITMP3, - super->index);
2813 codegen_addxcastrefs(cd, mcodeptr);
2814 M_ALD(REG_ITMP3, REG_ITMP2,
2815 OFFSET(vftbl_t, interfacetable[0]) -
2816 super->index * sizeof(methodptr*));
2819 codegen_addxcastrefs(cd, mcodeptr);
2822 M_BEQ(8 + (s1 == REG_ITMP1));
2823 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2824 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2825 codegen_threadcritstart(cd, (u1*) mcodeptr - cd->mcodebase);
2827 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2828 a = dseg_addaddress(cd, (void*) super->vftbl);
2829 M_ALD(REG_ITMP2, REG_PV, a);
2830 if (d != REG_ITMP1) {
2831 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2832 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2833 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2834 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2836 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2839 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2840 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2841 M_ALD(REG_ITMP2, REG_PV, a);
2842 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2843 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2844 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2847 M_CMPU(REG_ITMP3, REG_ITMP2);
2849 codegen_addxcastrefs(cd, mcodeptr);
2853 panic ("internal error: no inlined array checkcast");
2856 store_reg_to_var_int(iptr->dst, d);
2859 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
2861 var_to_reg_int(s1, src, REG_ITMP1);
2864 codegen_addxcheckarefs(cd, mcodeptr);
2867 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
2869 M_CMPI(REG_RESULT, 0);
2871 codegen_addxexceptionrefs(cd, mcodeptr);
2874 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2875 /* op1 = dimension, val.a = array descriptor */
2877 /* check for negative sizes and copy sizes to stack if necessary */
2879 MCODECHECK((iptr->op1 << 1) + 64);
2881 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
2882 var_to_reg_int(s2, src, REG_ITMP1);
2885 codegen_addxcheckarefs(cd, mcodeptr);
2887 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
2889 if (src->varkind != ARGVAR) {
2890 M_IST(s2, REG_SP, 4 * (s1 + INT_ARG_CNT + 6));
2894 /* a0 = dimension count */
2896 ICONST(rd->argintregs[0], iptr->op1);
2898 /* a1 = arraydescriptor */
2900 a = dseg_addaddress(cd, iptr->val.a);
2901 M_ALD(rd->argintregs[1], REG_PV, a);
2903 /* a2 = pointer to dimensions = stack pointer */
2905 M_LDA(rd->argintregs[2], REG_SP, (INT_ARG_CNT + 6)*4);
2907 a = dseg_addaddress(cd, (void *) builtin_nmultianewarray);
2908 M_ALD(REG_PV, REG_PV, a);
2911 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2914 M_LDA (REG_PV, REG_ITMP1, -s1);
2916 s4 ml = -s1, mh = 0;
2917 while (ml < -32768) {ml += 65536; mh--;}
2918 M_LDA(REG_PV, REG_ITMP1, ml);
2919 M_LDAH(REG_PV, REG_PV, mh);
2921 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2922 M_INTMOVE(REG_RESULT, s1);
2923 store_reg_to_var_int(iptr->dst, s1);
2927 default: error ("Unknown pseudo command: %d", iptr->opc);
2931 } /* for instruction */
2933 /* copy values to interface registers */
2935 src = bptr->outstack;
2936 len = bptr->outdepth;
2937 MCODECHECK(64 + len);
2940 if ((src->varkind != STACKVAR)) {
2942 if (IS_FLT_DBL_TYPE(s2)) {
2943 var_to_reg_flt(s1, src, REG_FTMP1);
2944 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
2945 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
2948 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
2952 var_to_reg_int(s1, src, REG_ITMP1);
2953 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
2954 M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
2957 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
2958 if (IS_2_WORD_TYPE(s2))
2959 M_IST(rd->secondregs[s1], REG_SP, rd->interfaces[len][s2].regoff * 4 + 4);
2965 } /* if (bptr -> flags >= BBREACHED) */
2966 } /* for basic block */
2968 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
2971 /* generate bound check stubs */
2973 s4 *xcodeptr = NULL;
2976 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
2977 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
2979 (u1 *) mcodeptr - cd->mcodebase);
2983 /* move index register into REG_ITMP1 */
2984 M_MOV(bref->reg, REG_ITMP1);
2985 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
2987 if (xcodeptr != NULL) {
2988 M_BR(xcodeptr - mcodeptr - 1);
2991 xcodeptr = mcodeptr;
2993 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
2994 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
2996 M_MOV(REG_ITMP1, rd->argintregs[0]);
2998 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
2999 M_ALD(REG_ITMP2, REG_PV, a);
3002 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3004 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3005 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3007 a = dseg_addaddress(cd, asm_handle_exception);
3008 M_ALD(REG_ITMP3, REG_PV, a);
3015 /* generate negative array size check stubs */
3019 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3020 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3021 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3023 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3027 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3029 (u1 *) mcodeptr - cd->mcodebase);
3033 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3035 if (xcodeptr != NULL) {
3036 M_BR(xcodeptr - mcodeptr - 1);
3039 xcodeptr = mcodeptr;
3041 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3042 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3044 a = dseg_addaddress(cd, new_negativearraysizeexception);
3045 M_ALD(REG_ITMP2, REG_PV, a);
3048 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3050 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3051 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3053 a = dseg_addaddress(cd, asm_handle_exception);
3054 M_ALD(REG_ITMP3, REG_PV, a);
3061 /* generate cast check stubs */
3065 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3066 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3067 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3069 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3073 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3075 (u1 *) mcodeptr - cd->mcodebase);
3079 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3081 if (xcodeptr != NULL) {
3082 M_BR(xcodeptr - mcodeptr - 1);
3085 xcodeptr = mcodeptr;
3087 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3088 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3090 a = dseg_addaddress(cd, new_classcastexception);
3091 M_ALD(REG_ITMP2, REG_PV, a);
3094 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3096 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3097 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3099 a = dseg_addaddress(cd, asm_handle_exception);
3100 M_ALD(REG_ITMP3, REG_PV, a);
3107 /* generate exception check stubs */
3111 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3112 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3113 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3115 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3119 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3121 (u1 *) mcodeptr - cd->mcodebase);
3125 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3127 if (xcodeptr != NULL) {
3128 M_BR(xcodeptr - mcodeptr - 1);
3131 xcodeptr = mcodeptr;
3133 /* XXX this cannot work - there is no link area */
3134 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3135 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3137 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3138 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3139 M_ALD(REG_ITMP2, REG_PV, a);
3143 /* get the exceptionptr from the ptrprt and clear it */
3144 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3146 M_AST(REG_ITMP3, REG_RESULT, 0);
3148 a = dseg_addaddress(cd, &_exceptionptr);
3149 M_ALD(REG_ITMP2, REG_PV, a);
3151 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);
3153 M_AST(REG_ITMP3, REG_ITMP2, 0);
3156 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3157 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3159 a = dseg_addaddress(cd, asm_handle_exception);
3160 M_ALD(REG_ITMP3, REG_PV, a);
3166 /* generate null pointer check stubs */
3170 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3171 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3172 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3174 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3178 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3180 (u1 *) mcodeptr - cd->mcodebase);
3184 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3186 if (xcodeptr != NULL) {
3187 M_BR(xcodeptr - mcodeptr - 1);
3190 xcodeptr = mcodeptr;
3192 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3193 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3195 a = dseg_addaddress(cd, new_nullpointerexception);
3196 M_ALD(REG_ITMP2, REG_PV, a);
3199 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3201 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3202 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3204 a = dseg_addaddress(cd, asm_handle_exception);
3205 M_ALD(REG_ITMP3, REG_PV, a);
3212 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
3214 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3218 /* function createcompilerstub *************************************************
3220 creates a stub routine which calls the compiler
3222 *******************************************************************************/
3224 #define COMPSTUBSIZE 6
3226 u1 *createcompilerstub(methodinfo *m)
3228 s4 *s = CNEW (s4, COMPSTUBSIZE); /* memory to hold the stub */
3229 s4 *mcodeptr = s; /* code generation pointer */
3231 M_LDA(2, REG_PV, 4*4);
3232 M_ALD(REG_PV, REG_PV, 5*4);
3236 s[4] = (s4) m; /* literals to be adressed */
3237 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3239 asm_cacheflush((void*) s, (u1*) mcodeptr - (u1*) s);
3241 #if defined(STATISTICS)
3243 count_cstub_len += COMPSTUBSIZE * 4;
3250 /* function removecompilerstub *************************************************
3252 deletes a compilerstub from memory (simply by freeing it)
3254 *******************************************************************************/
3256 void removecompilerstub(u1 *stub)
3258 CFREE(stub, COMPSTUBSIZE * 4);
3262 /* function: createnativestub **************************************************
3264 creates a stub routine which calls a native method
3266 *******************************************************************************/
3268 #define NATIVESTUBSIZE 200
3269 #define NATIVESTUBOFFSET 9
3271 u1 *createnativestub(functionptr f, methodinfo *m)
3273 s4 *s; /* memory to hold the stub */
3275 s4 *mcodeptr; /* code generation pointer */
3276 s4 stackframesize = 0; /* size of stackframe if needed */
3279 t_inlining_globals *id;
3282 /* mark start of dump memory area */
3284 dumpsize = dump_size();
3286 /* setup registers before using it */
3288 rd = DNEW(registerdata);
3289 id = DNEW(t_inlining_globals);
3291 inlining_setup(m, id);
3292 reg_setup(m, rd, id);
3294 descriptor2types(m); /* set paramcount and paramtypes */
3296 s = CNEW(s4, NATIVESTUBSIZE);
3297 cs = s + NATIVESTUBOFFSET;
3300 *(cs-1) = (u4) f; /* address of native method */
3301 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3302 *(cs-2) = (u4) builtin_get_exceptionptrptr;
3304 *(cs-2) = (u4) (&_exceptionptr); /* address of exceptionptr */
3306 *(cs-3) = (u4) asm_handle_nat_exception; /* addr of asm exception handler */
3307 *(cs-4) = (u4) (&env); /* addr of jni_environement */
3308 *(cs-5) = (u4) builtin_trace_args;
3310 *(cs-7) = (u4) builtin_displaymethodstop;
3311 *(cs-8) = (u4) m->class;
3312 *(cs-9) = (u4) asm_check_clinit;
3315 M_AST(REG_ITMP1, REG_SP, 8); /* store return address */
3316 M_LDA(REG_SP, REG_SP, -64); /* build up stackframe */
3318 /* if function is static, check for initialized */
3320 if (m->flags & ACC_STATIC) {
3321 /* if class isn't yet initialized, do it */
3322 if (!m->class->initialized) {
3323 /* call helper function which patches this code */
3324 M_ALD(REG_ITMP1, REG_PV, -8 * 4); /* class */
3325 M_ALD(REG_PV, REG_PV, -9 * 4); /* asm_check_clinit */
3328 disp = -(s4) (mcodeptr - cs) * 4;
3330 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3340 /* M_MFLR(REG_ITMP3); */
3341 /* XXX must be a multiple of 16 */
3342 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
3344 /* M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3348 /* save all arguments into the reserved stack space */
3349 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3350 t = m->paramtypes[p];
3352 if (IS_INT_LNG_TYPE(t)) {
3353 /* overlapping u8's are on the stack */
3354 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
3355 s1 = rd->argintregs[p + longargs + dblargs];
3357 if (!IS_2_WORD_TYPE(t)) {
3358 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3359 M_IST(s1, REG_SP, 24 + p * 8 + 4);
3362 M_IST(s1, REG_SP, 24 + p * 8);
3363 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3368 /* we do not have a data segment here */
3369 /* a = dseg_adds4(cd, 0xdeadbeef);
3370 M_ILD(REG_ITMP1, REG_PV, a); */
3371 M_LDA(REG_ITMP1, REG_ZERO, -1);
3372 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3373 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
3377 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3378 s1 = rd->argfltregs[fltargs + dblargs];
3380 if (!IS_2_WORD_TYPE(t)) {
3381 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3382 M_FST(s1, REG_SP, 24 + p * 8 + 4);
3386 M_DST(s1, REG_SP, 24 + p * 8);
3391 /* this should not happen */
3396 /* TODO: save remaining integer and flaot argument registers */
3398 /* load first 4 arguments into integer argument registers */
3399 for (p = 0; p < 8; p++) {
3400 d = rd->argintregs[p];
3401 M_ILD(d, REG_SP, 24 + p * 4);
3404 M_ALD(REG_ITMP1, REG_PV, -6 * 4);
3405 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
3406 M_ALD(REG_ITMP2, REG_PV, -5 * 4);
3414 /* restore arguments into the reserved stack space */
3415 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3416 t = m->paramtypes[p];
3418 if (IS_INT_LNG_TYPE(t)) {
3419 if ((p + longargs + dblargs) < INT_ARG_CNT) {
3420 s1 = rd->argintregs[p + longargs + dblargs];
3422 if (!IS_2_WORD_TYPE(t)) {
3423 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
3426 M_ILD(s1, REG_SP, 24 + p * 8);
3427 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3433 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3434 s1 = rd->argfltregs[fltargs + dblargs];
3436 if (!IS_2_WORD_TYPE(t)) {
3437 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
3441 M_DLD(s1, REG_SP, 24 + p * 8);
3448 /* M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3450 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
3451 /* M_MTLR(REG_ITMP3); */
3454 /* save argument registers on stack -- if we have to */
3455 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) ||
3456 m->paramcount > (INT_ARG_CNT - 1)) {
3458 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3459 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3461 stackframesize = stackparamcnt + paramshiftcnt;
3463 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
3465 panic("nativestub");
3468 if (m->flags & ACC_STATIC) {
3469 M_MOV(rd->argintregs[5], rd->argintregs[7]);
3470 M_MOV(rd->argintregs[4], rd->argintregs[6]);
3471 M_MOV(rd->argintregs[3], rd->argintregs[5]);
3472 M_MOV(rd->argintregs[2], rd->argintregs[4]);
3473 M_MOV(rd->argintregs[1], rd->argintregs[3]);
3474 M_MOV(rd->argintregs[0], rd->argintregs[2]);
3476 /* put class into second argument register */
3477 M_ALD(rd->argintregs[1], REG_PV, -8 * 4);
3480 M_MOV(rd->argintregs[6], rd->argintregs[7]);
3481 M_MOV(rd->argintregs[5], rd->argintregs[6]);
3482 M_MOV(rd->argintregs[4], rd->argintregs[5]);
3483 M_MOV(rd->argintregs[3], rd->argintregs[4]);
3484 M_MOV(rd->argintregs[2], rd->argintregs[3]);
3485 M_MOV(rd->argintregs[1], rd->argintregs[2]);
3486 M_MOV(rd->argintregs[0], rd->argintregs[1]);
3489 /* put env into first argument register */
3490 M_ALD(rd->argintregs[0], REG_PV, -4 * 4);
3492 M_ALD(REG_PV, REG_PV, -1 * 4); /* load adress of native method */
3495 disp = -(s4) (mcodeptr - cs) * 4;
3497 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3499 /* remove stackframe if there is one */
3500 if (stackframesize) {
3501 M_LDA(REG_SP, REG_SP, stackframesize * 8);
3504 /* 20 instructions */
3507 M_LDA(REG_SP, REG_SP, -10 * 8);
3508 M_DST(REG_FRESULT, REG_SP, 48+0);
3509 M_IST(REG_RESULT, REG_SP, 48+8);
3510 M_AST(REG_ITMP3, REG_SP, 48+12);
3511 M_IST(REG_RESULT2, REG_SP, 48+16);
3513 /* keep this order */
3514 switch (m->returntype) {
3517 M_MOV(REG_RESULT, rd->argintregs[2]);
3518 M_CLR(rd->argintregs[1]);
3522 M_MOV(REG_RESULT2, rd->argintregs[2]);
3523 M_MOV(REG_RESULT, rd->argintregs[1]);
3526 M_ALD(rd->argintregs[0], REG_PV, -6 * 4);
3528 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
3529 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
3530 M_ALD(REG_ITMP2, REG_PV, -7 * 4);/* builtin_displaymethodstop */
3533 M_DLD(REG_FRESULT, REG_SP, 48+0);
3534 M_ILD(REG_RESULT, REG_SP, 48+8);
3535 M_ALD(REG_ITMP3, REG_SP, 48+12);
3536 M_ILD(REG_RESULT2, REG_SP, 48+16);
3537 M_LDA(REG_SP, REG_SP, 10 * 8);
3541 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3542 if (IS_FLT_DBL_TYPE(m->returntype))
3543 if (IS_2_WORD_TYPE(m->returntype))
3544 M_DST(REG_FRESULT, REG_SP, 56);
3546 M_FST(REG_FRESULT, REG_SP, 56);
3548 M_IST(REG_RESULT, REG_SP, 56);
3549 if (IS_2_WORD_TYPE(m->returntype))
3550 M_IST(REG_RESULT2, REG_SP, 60);
3553 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* builtin_get_exceptionptrptr */
3556 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3558 M_LDA(REG_PV, REG_ITMP1, disp);
3559 M_MOV(REG_RESULT, REG_ITMP2);
3561 if (IS_FLT_DBL_TYPE(m->returntype))
3562 if (IS_2_WORD_TYPE(m->returntype))
3563 M_DLD(REG_FRESULT, REG_SP, 56);
3565 M_FLD(REG_FRESULT, REG_SP, 56);
3567 M_ILD(REG_RESULT, REG_SP, 56);
3568 if (IS_2_WORD_TYPE(m->returntype))
3569 M_ILD(REG_RESULT2, REG_SP, 60);
3572 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* get address of exceptionptr */
3574 M_ALD(REG_ITMP1, REG_ITMP2, 0); /* load exception into reg. itmp1 */
3576 M_BNE(4); /* if no exception then return */
3578 M_ALD(REG_ITMP1, REG_SP, 64 + 8); /* load return address */
3580 M_LDA(REG_SP, REG_SP, 64); /* remove stackframe */
3585 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
3587 M_ALD(REG_ITMP3, REG_SP, 64 + 8); /* load return address */
3589 M_LDA(REG_SP, REG_SP, 64); /* remove stackframe */
3591 M_LDA(REG_ITMP2, REG_ITMP1, -4); /* move fault address into reg. itmp2 */
3593 M_ALD(REG_ITMP3, REG_PV, -3 * 4); /* load asm exception handler address */
3598 dolog_plain("stubsize: %d (for %d params)\n", (int) (mcodeptr - (s4 *) s), m->paramcount);
3601 asm_cacheflush((void *) s, (u1*) mcodeptr - (u1*) s);
3603 #if defined(STATISTICS)
3605 count_nstub_len += NATIVESTUBSIZE * 4;
3608 /* release dump area */
3610 dump_release(dumpsize);
3612 return (u1*) (s + NATIVESTUBOFFSET);
3616 /* function: removenativestub **************************************************
3618 removes a previously created native-stub from memory
3620 *******************************************************************************/
3622 void removenativestub(u1 *stub)
3624 CFREE((s4 *) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 4);
3629 * These are local overrides for various environment variables in Emacs.
3630 * Please do not remove this and leave it at the end of the file, where
3631 * Emacs will automagically detect them.
3632 * ---------------------------------------------------------------------
3635 * indent-tabs-mode: t