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 2356 2005-04-22 17:33:35Z christian $
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 */
278 /* and Return Values to survive monitor_exit */
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);
350 /* take arguments out of register or stack frame */
356 for (p = 0, l = 0; p < m->paramcount; p++) {
357 arg = narg; iarg = niarg;
358 t = m->paramtypes[p];
359 var = &(rd->locals[l][t]);
361 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
365 if (IS_INT_LNG_TYPE(t)) { /* integer args */
366 if (iarg < INT_ARG_CNT -
367 (IS_2_WORD_TYPE(t)!=0)) { /* register arguments */
368 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
369 M_TINTMOVE(t, rd->argintregs[iarg], var->regoff);
371 } else { /* reg arg -> spilled */
372 M_IST(rd->argintregs[iarg], REG_SP, 4 * var->regoff);
373 if (IS_2_WORD_TYPE(t))
374 M_IST(rd->secondregs[rd->argintregs[iarg]], REG_SP, 4 * var->regoff + 4);
377 } else { /* stack arguments */
379 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
380 M_ILD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
381 if (IS_2_WORD_TYPE(t))
382 M_ILD(rd->secondregs[var->regoff], REG_SP, 4 * (parentargs_base + pa) + 4);
384 } else { /* stack arg -> spilled */
385 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa));
386 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff);
387 if (IS_2_WORD_TYPE(t)) {
388 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa) + 4);
389 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff + 4);
394 } else { /* floating args */
396 if (arg < FLT_ARG_CNT) { /* register arguments */
397 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
398 M_FLTMOVE(rd->argfltregs[arg], var->regoff);
400 } else { /* reg arg -> spilled */
401 if (IS_2_WORD_TYPE(t))
402 M_DST(rd->argfltregs[arg], REG_SP, 4 * var->regoff);
404 M_FST(rd->argfltregs[arg], REG_SP, 4 * var->regoff);
407 } else { /* stack arguments */
409 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
410 if (IS_2_WORD_TYPE(t))
411 M_DLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
414 M_FLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
416 } else { /* stack-arg -> spilled */
417 if (IS_2_WORD_TYPE(t)) {
418 M_DLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
419 M_DST(REG_FTMP1, REG_SP, 4 * var->regoff);
422 M_FLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
423 M_FST(REG_FTMP1, REG_SP, 4 * var->regoff);
431 /* save monitorenter argument */
433 #if defined(USE_THREADS)
434 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
435 if (m->flags & ACC_STATIC) {
436 p = dseg_addaddress(cd, m->class);
437 M_ALD(REG_ITMP1, REG_PV, p);
438 M_AST(REG_ITMP1, REG_SP, 4 * rd->maxmemuse);
441 M_AST(rd->argintregs[0], REG_SP, 4 * rd->maxmemuse);
445 /* call monitorenter function */
447 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
448 s4 func_enter = (m->flags & ACC_STATIC) ?
449 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
450 p = dseg_addaddress(cd, (void *) func_enter);
451 M_ALD(REG_ITMP3, REG_PV, p);
453 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
459 /* copy argument registers to stack and call trace function with pointer
460 to arguments on stack.
469 /* XXX must be a multiple of 16 */
470 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
472 M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
474 M_CLR(REG_ITMP1); /* clear help register */
476 /* save all arguments into the reserved stack space */
477 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
478 t = m->paramtypes[p];
480 if (IS_INT_LNG_TYPE(t)) {
481 /* overlapping u8's are on the stack */
482 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
483 s1 = rd->argintregs[p + longargs + dblargs];
485 if (!IS_2_WORD_TYPE(t)) {
486 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
487 M_IST(s1, REG_SP, 24 + p * 8 + 4);
490 M_IST(s1, REG_SP, 24 + p * 8);
491 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
496 a = dseg_adds4(cd, 0xdeadbeef);
497 M_ILD(REG_ITMP1, REG_PV, a);
498 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
499 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
503 if ((fltargs + dblargs) < FLT_ARG_CNT) {
504 s1 = rd->argfltregs[fltargs + dblargs];
506 if (!IS_2_WORD_TYPE(t)) {
507 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
508 M_FST(s1, REG_SP, 24 + p * 8 + 4);
512 M_DST(s1, REG_SP, 24 + p * 8);
517 /* this should not happen */
522 /* TODO: save remaining integer and flaot argument registers */
524 /* load first 4 arguments into integer argument registers */
525 for (p = 0; p < 8; p++) {
526 d = rd->argintregs[p];
527 M_ILD(d, REG_SP, 24 + p * 4);
530 p = dseg_addaddress(cd, m);
531 M_ALD(REG_ITMP1, REG_PV, p);
532 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
533 p = dseg_addaddress(cd, (void *) builtin_trace_args);
534 M_ALD(REG_ITMP2, REG_PV, p);
542 /* restore arguments into the reserved stack space */
543 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
544 t = m->paramtypes[p];
546 if (IS_INT_LNG_TYPE(t)) {
547 if ((p + longargs + dblargs) < INT_ARG_CNT) {
548 s1 = rd->argintregs[p + longargs + dblargs];
550 if (!IS_2_WORD_TYPE(t)) {
551 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
554 M_ILD(s1, REG_SP, 24 + p * 8);
555 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
561 if ((fltargs + dblargs) < FLT_ARG_CNT) {
562 s1 = rd->argfltregs[fltargs + dblargs];
564 if (!IS_2_WORD_TYPE(t)) {
565 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
569 M_DLD(s1, REG_SP, 24 + p * 8);
576 M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
578 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
587 /* end of header generation */
589 /* walk through all basic blocks */
590 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
592 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
594 if (bptr->flags >= BBREACHED) {
596 /* branch resolving */
600 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
601 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
607 /* copy interface registers to their destination */
615 while (src != NULL) {
617 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
618 /* d = reg_of_var(m, src, REG_ITMP1); */
619 if (!(src->flags & INMEMORY))
623 M_INTMOVE(REG_ITMP1, d);
624 store_reg_to_var_int(src, d);
630 while (src != NULL) {
632 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
633 d = reg_of_var(rd, src, REG_ITMP1);
634 M_INTMOVE(REG_ITMP1, d);
635 store_reg_to_var_int(src, d);
638 d = reg_of_var(rd, src, REG_IFTMP);
639 if ((src->varkind != STACKVAR)) {
641 if (IS_FLT_DBL_TYPE(s2)) {
642 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
643 s1 = rd->interfaces[len][s2].regoff;
647 if (IS_2_WORD_TYPE(s2)) {
648 M_DLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
651 M_FLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
654 store_reg_to_var_flt(src, d);
657 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
658 s1 = rd->interfaces[len][s2].regoff;
662 M_ILD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
663 if (IS_2_WORD_TYPE(s2))
664 M_ILD(rd->secondregs[d], REG_SP, 4 * rd->interfaces[len][s2].regoff + 4);
666 store_reg_to_var_int(src, d);
676 /* walk through all instructions */
680 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
682 MCODECHECK(64); /* an instruction usually needs < 64 words */
684 case ICMD_NOP: /* ... ==> ... */
685 case ICMD_INLINE_START:
686 case ICMD_INLINE_END:
689 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
691 var_to_reg_int(s1, src, REG_ITMP1);
694 codegen_addxnullrefs(cd, mcodeptr);
697 /* constant operations ************************************************/
699 case ICMD_ICONST: /* ... ==> ..., constant */
700 /* op1 = 0, val.i = constant */
702 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
703 ICONST(d, iptr->val.i);
704 store_reg_to_var_int(iptr->dst, d);
707 case ICMD_LCONST: /* ... ==> ..., constant */
708 /* op1 = 0, val.l = constant */
710 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
711 LCONST(d, iptr->val.l);
712 store_reg_to_var_int(iptr->dst, d);
715 case ICMD_FCONST: /* ... ==> ..., constant */
716 /* op1 = 0, val.f = constant */
718 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
719 a = dseg_addfloat(cd, iptr->val.f);
721 store_reg_to_var_flt(iptr->dst, d);
724 case ICMD_DCONST: /* ... ==> ..., constant */
725 /* op1 = 0, val.d = constant */
727 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
728 a = dseg_adddouble(cd, iptr->val.d);
730 store_reg_to_var_flt(iptr->dst, d);
733 case ICMD_ACONST: /* ... ==> ..., constant */
734 /* op1 = 0, val.a = constant */
736 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
737 ICONST(d, (u4) iptr->val.a);
738 store_reg_to_var_int(iptr->dst, d);
742 /* load/store operations **********************************************/
744 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
745 case ICMD_LLOAD: /* op1 = local variable */
748 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
749 if ((iptr->dst->varkind == LOCALVAR) &&
750 (iptr->dst->varnum == iptr->op1))
752 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
753 if (var->flags & INMEMORY) {
754 M_ILD(d, REG_SP, 4 * var->regoff);
755 if (IS_2_WORD_TYPE(var->type))
756 M_ILD(rd->secondregs[d], REG_SP, 4 * var->regoff + 4);
758 M_TINTMOVE(var->type, var->regoff, d);
760 store_reg_to_var_int(iptr->dst, d);
763 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
764 case ICMD_DLOAD: /* op1 = local variable */
766 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
767 if ((iptr->dst->varkind == LOCALVAR) &&
768 (iptr->dst->varnum == iptr->op1))
770 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
771 if (var->flags & INMEMORY)
772 if (IS_2_WORD_TYPE(var->type))
773 M_DLD(d, REG_SP, 4 * var->regoff);
775 M_FLD(d, REG_SP, 4 * var->regoff);
777 M_FLTMOVE(var->regoff, d);
779 store_reg_to_var_flt(iptr->dst, d);
783 case ICMD_ISTORE: /* ..., value ==> ... */
784 case ICMD_LSTORE: /* op1 = local variable */
787 if ((src->varkind == LOCALVAR) &&
788 (src->varnum == iptr->op1))
790 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
791 if (var->flags & INMEMORY) {
792 var_to_reg_int(s1, src, REG_ITMP1);
793 M_IST(s1, REG_SP, 4 * var->regoff);
794 if (IS_2_WORD_TYPE(var->type))
795 M_IST(rd->secondregs[s1], REG_SP, 4 * var->regoff + 4);
797 var_to_reg_int(s1, src, var->regoff);
798 M_TINTMOVE(var->type, s1, var->regoff);
802 case ICMD_FSTORE: /* ..., value ==> ... */
803 case ICMD_DSTORE: /* op1 = local variable */
805 if ((src->varkind == LOCALVAR) &&
806 (src->varnum == iptr->op1))
808 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
809 if (var->flags & INMEMORY) {
810 var_to_reg_flt(s1, src, REG_FTMP1);
811 if (var->type == TYPE_DBL)
812 M_DST(s1, REG_SP, 4 * var->regoff);
814 M_FST(s1, REG_SP, 4 * var->regoff);
816 var_to_reg_flt(s1, src, var->regoff);
817 M_FLTMOVE(s1, var->regoff);
822 /* pop/dup/swap operations ********************************************/
824 /* attention: double and longs are only one entry in CACAO ICMDs */
826 case ICMD_POP: /* ..., value ==> ... */
827 case ICMD_POP2: /* ..., value, value ==> ... */
830 case ICMD_DUP: /* ..., a ==> ..., a, a */
831 M_COPY(src, iptr->dst);
834 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
836 M_COPY(src, iptr->dst);
837 M_COPY(src->prev, iptr->dst->prev);
838 M_COPY(iptr->dst, iptr->dst->prev->prev);
841 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
843 M_COPY(src, iptr->dst);
844 M_COPY(src->prev, iptr->dst->prev);
845 M_COPY(src->prev->prev, iptr->dst->prev->prev);
846 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
849 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
851 M_COPY(src, iptr->dst);
852 M_COPY(src->prev, iptr->dst->prev);
855 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
857 M_COPY(src, iptr->dst);
858 M_COPY(src->prev, iptr->dst->prev);
859 M_COPY(src->prev->prev, iptr->dst->prev->prev);
860 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
861 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
864 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
866 M_COPY(src, iptr->dst);
867 M_COPY(src->prev, iptr->dst->prev);
868 M_COPY(src->prev->prev, iptr->dst->prev->prev);
869 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
870 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
871 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
874 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
876 M_COPY(src, iptr->dst->prev);
877 M_COPY(src->prev, iptr->dst);
881 /* integer operations *************************************************/
883 case ICMD_INEG: /* ..., 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_LNEG: /* ..., value ==> ..., - value */
893 var_to_reg_int(s1, src, REG_ITMP1);
894 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
895 M_SUBFIC(rd->secondregs[s1], 0, rd->secondregs[d]);
897 store_reg_to_var_int(iptr->dst, d);
900 case ICMD_I2L: /* ..., value ==> ..., value */
902 var_to_reg_int(s1, src, REG_ITMP2);
903 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
904 M_INTMOVE(s1, rd->secondregs[d]);
905 M_SRA_IMM(rd->secondregs[d], 31, d);
906 store_reg_to_var_int(iptr->dst, d);
909 case ICMD_L2I: /* ..., value ==> ..., value */
911 var_to_reg_int0(s1, src, REG_ITMP2, 0, 1);
912 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
914 store_reg_to_var_int(iptr->dst, d);
917 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
919 var_to_reg_int(s1, src, REG_ITMP1);
920 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
922 store_reg_to_var_int(iptr->dst, d);
925 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
927 var_to_reg_int(s1, src, REG_ITMP1);
928 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
930 store_reg_to_var_int(iptr->dst, d);
933 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
935 var_to_reg_int(s1, src, REG_ITMP1);
936 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
938 store_reg_to_var_int(iptr->dst, d);
942 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
944 var_to_reg_int(s1, src->prev, REG_ITMP1);
945 var_to_reg_int(s2, src, REG_ITMP2);
946 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
948 store_reg_to_var_int(iptr->dst, d);
951 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
952 /* val.i = constant */
954 var_to_reg_int(s1, src, REG_ITMP1);
955 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
956 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
957 M_IADD_IMM(s1, iptr->val.i, d);
960 ICONST(REG_ITMP2, iptr->val.i);
961 M_IADD(s1, REG_ITMP2, d);
963 store_reg_to_var_int(iptr->dst, d);
966 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
968 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
969 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
970 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
971 M_ADDC(s1, s2, rd->secondregs[d]);
972 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
973 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
975 store_reg_to_var_int(iptr->dst, d);
978 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
979 /* val.l = constant */
981 s3 = iptr->val.l & 0xffffffff;
982 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
983 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
984 if ((s3 >= -32768) && (s3 <= 32767)) {
985 M_ADDIC(s1, s3, rd->secondregs[d]);
988 ICONST(REG_ITMP2, s3);
989 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
991 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
992 s3 = iptr->val.l >> 32;
998 ICONST(REG_ITMP3, s3);
999 M_ADDE(s1, REG_ITMP3, d);
1001 store_reg_to_var_int(iptr->dst, d);
1004 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1006 var_to_reg_int(s1, src->prev, REG_ITMP1);
1007 var_to_reg_int(s2, src, REG_ITMP2);
1008 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1010 store_reg_to_var_int(iptr->dst, d);
1013 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1014 /* val.i = constant */
1016 var_to_reg_int(s1, src, REG_ITMP1);
1017 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1018 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
1019 M_IADD_IMM(s1, -iptr->val.i, d);
1022 ICONST(REG_ITMP2, -iptr->val.i);
1023 M_IADD(s1, REG_ITMP2, d);
1025 store_reg_to_var_int(iptr->dst, d);
1028 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1030 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1031 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1032 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1033 M_SUBC(s1, s2, rd->secondregs[d]);
1034 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1035 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1037 store_reg_to_var_int(iptr->dst, d);
1040 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1041 /* val.l = constant */
1043 s3 = (-iptr->val.l) & 0xffffffff;
1044 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1045 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1046 if ((s3 >= -32768) && (s3 <= 32767)) {
1047 M_ADDIC(s1, s3, rd->secondregs[d]);
1050 ICONST(REG_ITMP2, s3);
1051 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
1053 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1054 s3 = (-iptr->val.l) >> 32;
1060 ICONST(REG_ITMP3, s3);
1061 M_ADDE(s1, REG_ITMP3, d);
1063 store_reg_to_var_int(iptr->dst, d);
1066 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1067 var_to_reg_int(s1, src->prev, REG_ITMP1);
1068 var_to_reg_int(s2, src, REG_ITMP2);
1069 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1071 store_reg_to_var_int(iptr->dst, d);
1074 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1075 var_to_reg_int(s1, src->prev, REG_ITMP1);
1076 var_to_reg_int(s2, src, REG_ITMP2);
1077 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1081 store_reg_to_var_int(iptr->dst, d);
1084 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1086 var_to_reg_int(s1, src->prev, REG_ITMP1);
1087 var_to_reg_int(s2, src, REG_ITMP2);
1088 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1090 store_reg_to_var_int(iptr->dst, d);
1093 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1094 /* val.i = constant */
1096 var_to_reg_int(s1, src, REG_ITMP1);
1097 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1098 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1099 M_IMUL_IMM(s1, iptr->val.i, d);
1102 ICONST(REG_ITMP2, iptr->val.i);
1103 M_IMUL(s1, REG_ITMP2, d);
1105 store_reg_to_var_int(iptr->dst, d);
1108 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1110 var_to_reg_int(s1, src, REG_ITMP1);
1111 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1112 M_SRA_IMM(s1, iptr->val.i, d);
1114 store_reg_to_var_int(iptr->dst, d);
1117 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1119 var_to_reg_int(s1, src->prev, REG_ITMP1);
1120 var_to_reg_int(s2, src, REG_ITMP2);
1121 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1122 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1123 M_SLL(s1, REG_ITMP3, d);
1124 store_reg_to_var_int(iptr->dst, d);
1127 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1128 /* val.i = constant */
1130 var_to_reg_int(s1, src, REG_ITMP1);
1131 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1132 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1133 store_reg_to_var_int(iptr->dst, d);
1136 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1138 var_to_reg_int(s1, src->prev, REG_ITMP1);
1139 var_to_reg_int(s2, src, REG_ITMP2);
1140 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1141 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1142 M_SRA(s1, REG_ITMP3, d);
1143 store_reg_to_var_int(iptr->dst, d);
1146 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1147 /* val.i = constant */
1149 var_to_reg_int(s1, src, REG_ITMP1);
1150 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1151 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1152 store_reg_to_var_int(iptr->dst, d);
1155 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1157 var_to_reg_int(s1, src->prev, REG_ITMP1);
1158 var_to_reg_int(s2, src, REG_ITMP2);
1159 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1160 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1161 M_SRL(s1, REG_ITMP2, d);
1162 store_reg_to_var_int(iptr->dst, d);
1165 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1166 /* val.i = constant */
1168 var_to_reg_int(s1, src, REG_ITMP1);
1169 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1170 if (iptr->val.i & 0x1f)
1171 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1174 store_reg_to_var_int(iptr->dst, d);
1177 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1179 var_to_reg_int(s1, src->prev, REG_ITMP1);
1180 var_to_reg_int(s2, src, REG_ITMP2);
1181 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1183 store_reg_to_var_int(iptr->dst, d);
1186 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1187 /* val.i = constant */
1189 var_to_reg_int(s1, src, REG_ITMP1);
1190 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1191 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1192 M_AND_IMM(s1, iptr->val.i, d);
1195 else if (iptr->val.i == 0xffffff) {
1196 M_RLWINM(s1, 0, 8, 31, d);
1200 ICONST(REG_ITMP2, iptr->val.i);
1201 M_AND(s1, REG_ITMP2, d);
1203 store_reg_to_var_int(iptr->dst, d);
1206 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1208 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1209 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1210 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1211 M_AND(s1, s2, rd->secondregs[d]);
1212 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1213 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1215 store_reg_to_var_int(iptr->dst, d);
1218 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1219 /* val.l = constant */
1221 s3 = iptr->val.l & 0xffffffff;
1222 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1223 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1224 if ((s3 >= 0) && (s3 <= 65535)) {
1225 M_AND_IMM(s1, s3, rd->secondregs[d]);
1228 ICONST(REG_ITMP2, s3);
1229 M_AND(s1, REG_ITMP2, rd->secondregs[d]);
1231 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1232 s3 = iptr->val.l >> 32;
1233 if ((s3 >= 0) && (s3 <= 65535)) {
1234 M_AND_IMM(s1, s3, d);
1237 ICONST(REG_ITMP3, s3);
1238 M_AND(s1, REG_ITMP3, d);
1240 store_reg_to_var_int(iptr->dst, d);
1243 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1244 /* val.i = constant */
1246 var_to_reg_int(s1, src, REG_ITMP1);
1247 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1248 M_MOV(s1, REG_ITMP2);
1250 M_BGE(1 + 2*(iptr->val.i >= 32768));
1251 if (iptr->val.i >= 32768) {
1252 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1253 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1254 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1257 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1259 int b=0, m = iptr->val.i;
1262 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1264 M_ISUB(s1, REG_ITMP2, d);
1265 store_reg_to_var_int(iptr->dst, d);
1268 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1270 var_to_reg_int(s1, src->prev, REG_ITMP1);
1271 var_to_reg_int(s2, src, REG_ITMP2);
1272 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1274 store_reg_to_var_int(iptr->dst, d);
1277 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1278 /* val.i = constant */
1280 var_to_reg_int(s1, src, REG_ITMP1);
1281 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1282 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1283 M_OR_IMM(s1, iptr->val.i, d);
1286 ICONST(REG_ITMP2, iptr->val.i);
1287 M_OR(s1, REG_ITMP2, d);
1289 store_reg_to_var_int(iptr->dst, d);
1292 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1294 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1295 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1296 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1297 M_OR(s1, s2, rd->secondregs[d]);
1298 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1299 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1301 store_reg_to_var_int(iptr->dst, d);
1304 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1305 /* val.l = constant */
1307 s3 = iptr->val.l & 0xffffffff;
1308 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1309 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1310 if ((s3 >= 0) && (s3 <= 65535)) {
1311 M_OR_IMM(s1, s3, rd->secondregs[d]);
1314 ICONST(REG_ITMP2, s3);
1315 M_OR(s1, REG_ITMP2, rd->secondregs[d]);
1317 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1318 s3 = iptr->val.l >> 32;
1319 if ((s3 >= 0) && (s3 <= 65535)) {
1320 M_OR_IMM(s1, s3, d);
1323 ICONST(REG_ITMP3, s3);
1324 M_OR(s1, REG_ITMP3, d);
1326 store_reg_to_var_int(iptr->dst, d);
1329 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1331 var_to_reg_int(s1, src->prev, REG_ITMP1);
1332 var_to_reg_int(s2, src, REG_ITMP2);
1333 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1335 store_reg_to_var_int(iptr->dst, d);
1338 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1339 /* val.i = constant */
1341 var_to_reg_int(s1, src, REG_ITMP1);
1342 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1343 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1344 M_XOR_IMM(s1, iptr->val.i, d);
1347 ICONST(REG_ITMP2, iptr->val.i);
1348 M_XOR(s1, REG_ITMP2, d);
1350 store_reg_to_var_int(iptr->dst, d);
1353 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1355 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1356 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1357 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1358 M_XOR(s1, s2, rd->secondregs[d]);
1359 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1360 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1362 store_reg_to_var_int(iptr->dst, d);
1365 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1366 /* val.l = constant */
1368 s3 = iptr->val.l & 0xffffffff;
1369 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1370 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1371 if ((s3 >= 0) && (s3 <= 65535)) {
1372 M_XOR_IMM(s1, s3, rd->secondregs[d]);
1375 ICONST(REG_ITMP2, s3);
1376 M_XOR(s1, REG_ITMP2, rd->secondregs[d]);
1378 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1379 s3 = iptr->val.l >> 32;
1380 if ((s3 >= 0) && (s3 <= 65535)) {
1381 M_XOR_IMM(s1, s3, d);
1384 ICONST(REG_ITMP3, s3);
1385 M_XOR(s1, REG_ITMP3, d);
1387 store_reg_to_var_int(iptr->dst, d);
1390 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1392 var_to_reg_int0(s1, src->prev, REG_ITMP3, 1, 0);
1393 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
1394 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1397 (d==s1 || d==s2 || d==rd->secondregs[s1] || d==rd->secondregs[s2]);
1398 int dreg = tempreg ? REG_ITMP1 : d;
1400 M_IADD_IMM(REG_ZERO, 1, dreg);
1405 var_to_reg_int0(s1, src->prev, REG_ITMP3, 0, 1);
1406 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1410 M_IADD_IMM(dreg, -1, dreg);
1411 M_IADD_IMM(dreg, -1, dreg);
1412 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1413 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1416 store_reg_to_var_int(iptr->dst, d);
1419 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1420 /* op1 = variable, val.i = constant */
1422 var = &(rd->locals[iptr->op1][TYPE_INT]);
1423 if (var->flags & INMEMORY) {
1425 M_ILD(s1, REG_SP, 4 * var->regoff);
1434 M_ADDIS(s1, m>>16, s1);
1436 M_IADD_IMM(s1, m&0xffff, s1);
1438 if (var->flags & INMEMORY)
1439 M_IST(s1, REG_SP, 4 * var->regoff);
1443 /* floating operations ************************************************/
1445 case ICMD_FNEG: /* ..., value ==> ..., - value */
1447 var_to_reg_flt(s1, src, REG_FTMP1);
1448 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1450 store_reg_to_var_flt(iptr->dst, d);
1453 case ICMD_DNEG: /* ..., value ==> ..., - value */
1455 var_to_reg_flt(s1, src, REG_FTMP1);
1456 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1458 store_reg_to_var_flt(iptr->dst, d);
1461 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1463 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1464 var_to_reg_flt(s2, src, REG_FTMP2);
1465 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1467 store_reg_to_var_flt(iptr->dst, d);
1470 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1472 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1473 var_to_reg_flt(s2, src, REG_FTMP2);
1474 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1476 store_reg_to_var_flt(iptr->dst, d);
1479 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1481 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1482 var_to_reg_flt(s2, src, REG_FTMP2);
1483 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1485 store_reg_to_var_flt(iptr->dst, d);
1488 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1490 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1491 var_to_reg_flt(s2, src, REG_FTMP2);
1492 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1494 store_reg_to_var_flt(iptr->dst, d);
1497 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1499 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1500 var_to_reg_flt(s2, src, REG_FTMP2);
1501 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1503 store_reg_to_var_flt(iptr->dst, d);
1506 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1508 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1509 var_to_reg_flt(s2, src, REG_FTMP2);
1510 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1512 store_reg_to_var_flt(iptr->dst, d);
1515 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1517 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1518 var_to_reg_flt(s2, src, REG_FTMP2);
1519 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1521 store_reg_to_var_flt(iptr->dst, d);
1524 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / 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_FTMP3);
1530 store_reg_to_var_flt(iptr->dst, d);
1533 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1535 var_to_reg_flt(s1, src, REG_FTMP1);
1536 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1538 a = dseg_addfloat(cd, 0.0);
1539 M_FLD(REG_FTMP2, REG_PV, a);
1540 M_FCMPU(s1, REG_FTMP2);
1542 a = dseg_adds4(cd, 0);
1543 M_CVTDL_C(s1, REG_FTMP1);
1544 M_LDA (REG_ITMP1, REG_PV, a);
1545 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1546 M_ILD (d, REG_PV, a);
1547 store_reg_to_var_int(iptr->dst, d);
1550 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1552 var_to_reg_flt(s1, src, REG_FTMP1);
1553 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1555 store_reg_to_var_flt(iptr->dst, d);
1558 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1560 var_to_reg_flt(s1, src, REG_FTMP1);
1561 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1563 store_reg_to_var_flt(iptr->dst, d);
1566 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1568 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1569 var_to_reg_flt(s2, src, REG_FTMP2);
1570 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1572 M_IADD_IMM(0, -1, d);
1575 M_IADD_IMM(0, 0, d);
1577 M_IADD_IMM(0, 1, d);
1578 store_reg_to_var_int(iptr->dst, d);
1581 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1583 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1584 var_to_reg_flt(s2, src, REG_FTMP2);
1585 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1587 M_IADD_IMM(0, 1, d);
1590 M_IADD_IMM(0, 0, d);
1592 M_IADD_IMM(0, -1, d);
1593 store_reg_to_var_int(iptr->dst, d);
1597 /* memory operations **************************************************/
1599 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1601 var_to_reg_int(s1, src, REG_ITMP1);
1602 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1603 gen_nullptr_check(s1);
1604 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1605 store_reg_to_var_int(iptr->dst, d);
1608 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1610 var_to_reg_int(s1, src->prev, REG_ITMP1);
1611 var_to_reg_int(s2, src, REG_ITMP2);
1612 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1613 if (iptr->op1 == 0) {
1614 gen_nullptr_check(s1);
1617 M_SLL_IMM(s2, 2, REG_ITMP2);
1618 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1619 M_LWZX(d, s1, REG_ITMP2);
1620 store_reg_to_var_int(iptr->dst, d);
1623 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1625 var_to_reg_int(s1, src->prev, REG_ITMP1);
1626 var_to_reg_int(s2, src, REG_ITMP2);
1627 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1628 if (iptr->op1 == 0) {
1629 gen_nullptr_check(s1);
1632 M_SLL_IMM(s2, 3, REG_ITMP2);
1633 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1634 M_ILD(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
1635 M_ILD(rd->secondregs[d], REG_ITMP2, OFFSET(java_longarray, data[0])+4);
1636 store_reg_to_var_int(iptr->dst, d);
1639 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1641 var_to_reg_int(s1, src->prev, REG_ITMP1);
1642 var_to_reg_int(s2, src, REG_ITMP2);
1643 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1644 if (iptr->op1 == 0) {
1645 gen_nullptr_check(s1);
1648 M_SLL_IMM(s2, 2, REG_ITMP2);
1649 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1650 M_LWZX(d, s1, REG_ITMP2);
1651 store_reg_to_var_int(iptr->dst, d);
1654 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1656 var_to_reg_int(s1, src->prev, REG_ITMP1);
1657 var_to_reg_int(s2, src, REG_ITMP2);
1658 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1659 if (iptr->op1 == 0) {
1660 gen_nullptr_check(s1);
1663 M_SLL_IMM(s2, 2, REG_ITMP2);
1664 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1665 M_LFSX(d, s1, REG_ITMP2);
1666 store_reg_to_var_flt(iptr->dst, d);
1669 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1671 var_to_reg_int(s1, src->prev, REG_ITMP1);
1672 var_to_reg_int(s2, src, REG_ITMP2);
1673 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1674 if (iptr->op1 == 0) {
1675 gen_nullptr_check(s1);
1678 M_SLL_IMM(s2, 3, REG_ITMP2);
1679 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1680 M_LFDX(d, s1, REG_ITMP2);
1681 store_reg_to_var_flt(iptr->dst, d);
1684 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1686 var_to_reg_int(s1, src->prev, REG_ITMP1);
1687 var_to_reg_int(s2, src, REG_ITMP2);
1688 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1689 if (iptr->op1 == 0) {
1690 gen_nullptr_check(s1);
1693 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1694 M_LBZX(d, s1, REG_ITMP2);
1696 store_reg_to_var_int(iptr->dst, d);
1699 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1701 var_to_reg_int(s1, src->prev, REG_ITMP1);
1702 var_to_reg_int(s2, src, REG_ITMP2);
1703 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1704 if (iptr->op1 == 0) {
1705 gen_nullptr_check(s1);
1708 M_SLL_IMM(s2, 1, REG_ITMP2);
1709 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1710 M_LHAX(d, s1, REG_ITMP2);
1711 store_reg_to_var_int(iptr->dst, d);
1714 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1716 var_to_reg_int(s1, src->prev, REG_ITMP1);
1717 var_to_reg_int(s2, src, REG_ITMP2);
1718 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1719 if (iptr->op1 == 0) {
1720 gen_nullptr_check(s1);
1723 M_SLL_IMM(s2, 1, REG_ITMP2);
1724 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1725 M_LHZX(d, s1, REG_ITMP2);
1726 store_reg_to_var_int(iptr->dst, d);
1729 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1731 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1732 var_to_reg_int(s2, src->prev, REG_ITMP2);
1733 if (iptr->op1 == 0) {
1734 gen_nullptr_check(s1);
1737 var_to_reg_int0(s3, src, REG_ITMP3, 1, 0);
1738 M_SLL_IMM(s2, 3, REG_ITMP2);
1739 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1740 M_STWX(s3, s1, REG_ITMP2);
1741 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1742 var_to_reg_int0(s3, src, REG_ITMP3, 0, 1);
1743 M_STWX(s3, s1, REG_ITMP2);
1746 case ICMD_IASTORE: /* ..., 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_SLL_IMM(s2, 2, REG_ITMP2);
1756 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1757 M_STWX(s3, s1, REG_ITMP2);
1760 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1762 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1763 var_to_reg_int(s2, src->prev, REG_ITMP2);
1764 if (iptr->op1 == 0) {
1765 gen_nullptr_check(s1);
1768 var_to_reg_flt(s3, src, REG_FTMP3);
1769 M_SLL_IMM(s2, 2, REG_ITMP2);
1770 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1771 M_STFSX(s3, s1, REG_ITMP2);
1774 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1776 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1777 var_to_reg_int(s2, src->prev, REG_ITMP2);
1778 if (iptr->op1 == 0) {
1779 gen_nullptr_check(s1);
1782 var_to_reg_flt(s3, src, REG_FTMP3);
1783 M_SLL_IMM(s2, 3, REG_ITMP2);
1784 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1785 M_STFDX(s3, s1, REG_ITMP2);
1788 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1790 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1791 var_to_reg_int(s2, src->prev, REG_ITMP2);
1792 if (iptr->op1 == 0) {
1793 gen_nullptr_check(s1);
1796 var_to_reg_int(s3, src, REG_ITMP3);
1797 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1798 M_STBX(s3, s1, REG_ITMP2);
1801 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1803 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1804 var_to_reg_int(s2, src->prev, REG_ITMP2);
1805 if (iptr->op1 == 0) {
1806 gen_nullptr_check(s1);
1809 var_to_reg_int(s3, src, REG_ITMP3);
1810 M_SLL_IMM(s2, 1, REG_ITMP2);
1811 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1812 M_STHX(s3, s1, REG_ITMP2);
1815 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1817 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1818 var_to_reg_int(s2, src->prev, REG_ITMP2);
1819 if (iptr->op1 == 0) {
1820 gen_nullptr_check(s1);
1823 var_to_reg_int(s3, src, REG_ITMP3);
1824 M_SLL_IMM(s2, 1, REG_ITMP2);
1825 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1826 M_STHX(s3, s1, REG_ITMP2);
1829 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1830 /* op1 = type, val.a = field address */
1832 /* if class isn't yet initialized, do it */
1833 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1834 /* call helper function which patches this code */
1835 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1836 M_ALD(REG_ITMP1, REG_PV, a);
1837 a = dseg_addaddress(cd, asm_check_clinit);
1838 M_ALD(REG_PV, REG_PV, a);
1843 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1845 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1847 s4 ml = -s1, mh = 0;
1848 while (ml < -32768) { ml += 65536; mh--; }
1849 M_LDA(REG_PV, REG_ITMP1, ml);
1850 M_LDAH(REG_PV, REG_PV, mh);
1854 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1855 M_ALD(REG_ITMP1, REG_PV, a);
1856 switch (iptr->op1) {
1858 var_to_reg_int(s2, src, REG_ITMP2);
1859 M_IST(s2, REG_ITMP1, 0);
1862 var_to_reg_int(s2, src, REG_ITMP3);
1863 M_IST(s2, REG_ITMP1, 0);
1864 M_IST(rd->secondregs[s2], REG_ITMP1, 4);
1867 var_to_reg_int(s2, src, REG_ITMP2);
1868 M_AST(s2, REG_ITMP1, 0);
1871 var_to_reg_flt(s2, src, REG_FTMP2);
1872 M_FST(s2, REG_ITMP1, 0);
1875 var_to_reg_flt(s2, src, REG_FTMP2);
1876 M_DST(s2, REG_ITMP1, 0);
1878 default: panic ("internal error");
1882 case ICMD_GETSTATIC: /* ... ==> ..., value */
1883 /* op1 = type, val.a = field address */
1885 /* if class isn't yet initialized, do it */
1886 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1887 /* call helper function which patches this code */
1888 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1889 M_ALD(REG_ITMP1, REG_PV, a);
1890 a = dseg_addaddress(cd, asm_check_clinit);
1891 M_ALD(REG_PV, REG_PV, a);
1896 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1898 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1900 s4 ml = -s1, mh = 0;
1901 while (ml < -32768) { ml += 65536; mh--; }
1902 M_LDA(REG_PV, REG_ITMP1, ml);
1903 M_LDAH(REG_PV, REG_PV, mh);
1907 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1908 M_ALD(REG_ITMP1, REG_PV, a);
1909 switch (iptr->op1) {
1911 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1912 M_ILD(d, REG_ITMP1, 0);
1913 store_reg_to_var_int(iptr->dst, d);
1916 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1917 M_ILD(d, REG_ITMP1, 0);
1918 M_ILD(rd->secondregs[d], REG_ITMP1, 4);
1919 store_reg_to_var_int(iptr->dst, d);
1922 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1923 M_ALD(d, REG_ITMP1, 0);
1924 store_reg_to_var_int(iptr->dst, d);
1927 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1928 M_FLD(d, REG_ITMP1, 0);
1929 store_reg_to_var_flt(iptr->dst, d);
1932 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1933 M_DLD(d, REG_ITMP1, 0);
1934 store_reg_to_var_flt(iptr->dst, d);
1936 default: panic ("internal error");
1941 case ICMD_PUTFIELD: /* ..., value ==> ... */
1942 /* op1 = type, val.i = field offset */
1944 a = ((fieldinfo *)(iptr->val.a))->offset;
1945 switch (iptr->op1) {
1947 var_to_reg_int(s1, src->prev, REG_ITMP1);
1948 var_to_reg_int(s2, src, REG_ITMP2);
1949 gen_nullptr_check(s1);
1953 var_to_reg_int(s1, src->prev, REG_ITMP1);
1954 var_to_reg_int(s2, src, REG_ITMP3);
1955 gen_nullptr_check(s1);
1957 M_IST(rd->secondregs[s2], s1, a+4);
1960 var_to_reg_int(s1, src->prev, REG_ITMP1);
1961 var_to_reg_int(s2, src, REG_ITMP2);
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);
1972 var_to_reg_int(s1, src->prev, REG_ITMP1);
1973 var_to_reg_flt(s2, src, REG_FTMP2);
1974 gen_nullptr_check(s1);
1977 default: panic ("internal error");
1981 case ICMD_GETFIELD: /* ... ==> ..., value */
1982 /* op1 = type, val.i = field offset */
1984 a = ((fieldinfo *)(iptr->val.a))->offset;
1985 switch (iptr->op1) {
1987 var_to_reg_int(s1, src, REG_ITMP1);
1988 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1989 gen_nullptr_check(s1);
1991 store_reg_to_var_int(iptr->dst, d);
1994 var_to_reg_int(s1, src, REG_ITMP1);
1995 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1996 gen_nullptr_check(s1);
1998 M_ILD(rd->secondregs[d], s1, a+4);
1999 store_reg_to_var_int(iptr->dst, d);
2002 var_to_reg_int(s1, src, REG_ITMP1);
2003 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2004 gen_nullptr_check(s1);
2006 store_reg_to_var_int(iptr->dst, d);
2009 var_to_reg_int(s1, src, REG_ITMP1);
2010 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2011 gen_nullptr_check(s1);
2013 store_reg_to_var_flt(iptr->dst, d);
2016 var_to_reg_int(s1, src, REG_ITMP1);
2017 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2018 gen_nullptr_check(s1);
2020 store_reg_to_var_flt(iptr->dst, d);
2022 default: panic ("internal error");
2027 /* branch operations **************************************************/
2029 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2031 a = dseg_addaddress(cd, asm_handle_exception);
2032 M_ALD(REG_ITMP2, REG_PV, a);
2034 var_to_reg_int(s1, src, REG_ITMP1);
2035 M_INTMOVE(s1, REG_ITMP1_XPTR);
2037 if (m->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
2038 M_BL(0); /* get current PC */
2039 M_MFLR(REG_ITMP2_XPC);
2040 if (m->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
2041 M_RTS; /* jump to CTR */
2046 case ICMD_GOTO: /* ... ==> ... */
2047 /* op1 = target JavaVM pc */
2049 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2053 case ICMD_JSR: /* ... ==> ... */
2054 /* op1 = target JavaVM pc */
2056 if (m->isleafmethod) M_MFLR(REG_ITMP2);
2059 M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
2060 if (m->isleafmethod) M_MTLR(REG_ITMP2);
2062 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2065 case ICMD_RET: /* ... ==> ... */
2066 /* op1 = local variable */
2068 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2069 if (var->flags & INMEMORY) {
2070 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
2074 M_MTCTR(var->regoff);
2079 case ICMD_IFNULL: /* ..., value ==> ... */
2080 /* op1 = target JavaVM pc */
2082 var_to_reg_int(s1, src, REG_ITMP1);
2085 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2088 case ICMD_IFNONNULL: /* ..., value ==> ... */
2089 /* op1 = target JavaVM pc */
2091 var_to_reg_int(s1, src, REG_ITMP1);
2094 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2102 case ICMD_IFEQ: /* ..., value ==> ... */
2103 /* op1 = target JavaVM pc, val.i = constant */
2105 var_to_reg_int(s1, src, REG_ITMP1);
2106 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2107 M_CMPI(s1, iptr->val.i);
2110 ICONST(REG_ITMP2, iptr->val.i);
2111 M_CMP(s1, REG_ITMP2);
2134 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2138 case ICMD_IF_LEQ: /* ..., value ==> ... */
2139 /* op1 = target JavaVM pc, val.l = constant */
2141 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2142 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2143 if (iptr->val.l == 0) {
2144 M_OR(s1, s2, REG_ITMP3);
2145 M_CMPI(REG_ITMP3, 0);
2147 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2148 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2150 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2153 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2154 M_CMP(s2, REG_ITMP3);
2156 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2157 M_CMP(s1, REG_ITMP3)
2160 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2163 case ICMD_IF_LLT: /* ..., value ==> ... */
2164 /* op1 = target JavaVM pc, val.l = constant */
2165 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2166 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2167 /* if (iptr->val.l == 0) { */
2168 /* M_OR(s1, s2, REG_ITMP3); */
2169 /* M_CMPI(REG_ITMP3, 0); */
2172 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2173 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2175 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2177 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2180 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2181 M_CMP(s2, REG_ITMP3);
2183 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2185 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2186 M_CMP(s1, REG_ITMP3)
2189 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2192 case ICMD_IF_LLE: /* ..., value ==> ... */
2193 /* op1 = target JavaVM pc, val.l = constant */
2195 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2196 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2197 /* if (iptr->val.l == 0) { */
2198 /* M_OR(s1, s2, REG_ITMP3); */
2199 /* M_CMPI(REG_ITMP3, 0); */
2202 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2203 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2205 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2207 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2210 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2211 M_CMP(s2, REG_ITMP3);
2213 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2215 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2216 M_CMP(s1, REG_ITMP3)
2219 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2222 case ICMD_IF_LNE: /* ..., value ==> ... */
2223 /* op1 = target JavaVM pc, val.l = constant */
2225 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2226 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2227 if (iptr->val.l == 0) {
2228 M_OR(s1, s2, REG_ITMP3);
2229 M_CMPI(REG_ITMP3, 0);
2231 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2232 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2234 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2237 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2238 M_CMP(s2, REG_ITMP3);
2240 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2241 M_CMP(s1, REG_ITMP3)
2244 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2247 case ICMD_IF_LGT: /* ..., value ==> ... */
2248 /* op1 = target JavaVM pc, val.l = constant */
2250 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2251 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2252 /* if (iptr->val.l == 0) { */
2253 /* M_OR(s1, s2, REG_ITMP3); */
2254 /* M_CMPI(REG_ITMP3, 0); */
2257 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2258 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2260 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2262 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2265 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2266 M_CMP(s2, REG_ITMP3);
2268 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2270 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2271 M_CMP(s1, REG_ITMP3)
2274 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2277 case ICMD_IF_LGE: /* ..., value ==> ... */
2278 /* op1 = target JavaVM pc, val.l = constant */
2279 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2280 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2281 /* if (iptr->val.l == 0) { */
2282 /* M_OR(s1, s2, REG_ITMP3); */
2283 /* M_CMPI(REG_ITMP3, 0); */
2286 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2287 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2289 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2291 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2294 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2295 M_CMP(s2, REG_ITMP3);
2297 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2299 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2300 M_CMP(s1, REG_ITMP3)
2303 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2307 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2308 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2309 case ICMD_IF_ACMPEQ:
2311 var_to_reg_int(s1, src->prev, REG_ITMP1);
2312 var_to_reg_int(s2, src, REG_ITMP2);
2315 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2318 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2319 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2320 case ICMD_IF_ACMPNE:
2322 var_to_reg_int(s1, src->prev, REG_ITMP1);
2323 var_to_reg_int(s2, src, REG_ITMP2);
2326 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2329 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2330 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2332 var_to_reg_int(s1, src->prev, REG_ITMP1);
2333 var_to_reg_int(s2, src, REG_ITMP2);
2336 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2339 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2340 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2342 var_to_reg_int(s1, src->prev, REG_ITMP1);
2343 var_to_reg_int(s2, src, REG_ITMP2);
2346 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2349 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2350 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2352 var_to_reg_int(s1, src->prev, REG_ITMP1);
2353 var_to_reg_int(s2, src, REG_ITMP2);
2356 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2359 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2360 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2362 var_to_reg_int(s1, src->prev, REG_ITMP1);
2363 var_to_reg_int(s2, src, REG_ITMP2);
2366 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2369 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2372 var_to_reg_int(s1, src, REG_RESULT);
2373 M_TINTMOVE(src->type, s1, REG_RESULT);
2374 goto nowperformreturn;
2376 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2378 var_to_reg_flt(s1, src, REG_FRESULT);
2379 M_FLTMOVE(s1, REG_FRESULT);
2380 goto nowperformreturn;
2382 case ICMD_RETURN: /* ... ==> ... */
2390 p = parentargs_base;
2391 /* call trace function */
2395 M_LDA(REG_SP, REG_SP, -10 * 8);
2396 M_DST(REG_FRESULT, REG_SP, 48+0);
2397 M_IST(REG_RESULT, REG_SP, 48+8);
2398 M_AST(REG_ITMP3, REG_SP, 48+12);
2399 M_IST(REG_RESULT2, REG_SP, 48+16);
2400 a = dseg_addaddress(cd, m);
2402 /* keep this order */
2403 switch (iptr->opc) {
2406 M_MOV(REG_RESULT, rd->argintregs[2]);
2407 M_CLR(rd->argintregs[1]);
2411 M_MOV(REG_RESULT2, rd->argintregs[2]);
2412 M_MOV(REG_RESULT, rd->argintregs[1]);
2415 M_ALD(rd->argintregs[0], REG_PV, a);
2417 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2418 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2419 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2420 M_ALD(REG_ITMP2, REG_PV, a);
2423 M_DLD(REG_FRESULT, REG_SP, 48+0);
2424 M_ILD(REG_RESULT, REG_SP, 48+8);
2425 M_ALD(REG_ITMP3, REG_SP, 48+12);
2426 M_ILD(REG_RESULT2, REG_SP, 48+16);
2427 M_LDA(REG_SP, REG_SP, 10 * 8);
2431 #if defined(USE_THREADS)
2432 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2433 /* we need to save the proper return value */
2434 switch (iptr->opc) {
2437 M_IST(REG_RESULT , REG_SP, rd->maxmemuse * 4 + 4);
2439 M_IST(REG_RESULT2, REG_SP, rd->maxmemuse * 4 + 8);
2442 M_FST(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2445 M_DST(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2449 a = dseg_addaddress(cd, (void *) (builtin_monitorexit));
2450 M_ALD(REG_ITMP3, REG_PV, a);
2452 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
2455 /* and now restore the proper return value */
2456 switch (iptr->opc) {
2459 M_ILD(REG_RESULT , REG_SP, rd->maxmemuse * 4 + 4);
2461 M_ILD(REG_RESULT2, REG_SP, rd->maxmemuse * 4 + 8);
2464 M_FLD(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2467 M_DLD(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2473 /* restore return address */
2475 if (!m->isleafmethod) {
2476 M_ALD(REG_ITMP3, REG_SP, 4 * p + 8);
2480 /* restore saved registers */
2482 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2483 p--; M_ILD(rd->savintregs[i], REG_SP, 4 * p);
2485 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2486 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, 4 * p);
2489 /* deallocate stack */
2491 if (parentargs_base) {
2492 M_LDA(REG_SP, REG_SP, parentargs_base*4);
2503 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2508 tptr = (void **) iptr->target;
2510 s4ptr = iptr->val.a;
2511 l = s4ptr[1]; /* low */
2512 i = s4ptr[2]; /* high */
2514 var_to_reg_int(s1, src, REG_ITMP1);
2516 M_INTMOVE(s1, REG_ITMP1);
2517 } else if (l <= 32768) {
2518 M_LDA(REG_ITMP1, s1, -l);
2520 ICONST(REG_ITMP2, l);
2521 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2527 M_CMPUI(REG_ITMP1, i - 1);
2530 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2531 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2533 /* build jump table top down and use address of lowest entry */
2535 /* s4ptr += 3 + i; */
2539 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2540 dseg_addtarget(cd, (basicblock *) tptr[0]);
2545 /* length of dataseg after last dseg_addtarget is used by load */
2547 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2548 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2549 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2556 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2558 s4 i, l, val, *s4ptr;
2561 tptr = (void **) iptr->target;
2563 s4ptr = iptr->val.a;
2564 l = s4ptr[0]; /* default */
2565 i = s4ptr[1]; /* count */
2567 MCODECHECK((i<<2)+8);
2568 var_to_reg_int(s1, src, REG_ITMP1);
2574 if ((val >= -32768) && (val <= 32767)) {
2578 a = dseg_adds4(cd, val);
2579 M_ILD(REG_ITMP2, REG_PV, a);
2580 M_CMP(s1, REG_ITMP2);
2583 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2584 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2588 /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2590 tptr = (void **) iptr->target;
2591 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2598 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2599 /* op1 = return type, val.a = function pointer*/
2603 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2604 /* op1 = return type, val.a = function pointer*/
2608 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2609 /* op1 = return type, val.a = function pointer*/
2613 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2614 /* op1 = arg count, val.a = method pointer */
2616 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2617 /* op1 = arg count, val.a = method pointer */
2619 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2620 /* op1 = arg count, val.a = method pointer */
2622 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2623 /* op1 = arg count, val.a = method pointer */
2631 MCODECHECK((s3 << 1) + 64);
2634 /* copy arguments to registers or stack location */
2636 stackptr srcsave = src;
2640 for (; --s3 >= 0; src = src->prev) {
2641 argsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
2642 if (IS_FLT_DBL_TYPE(src->type))
2646 for (s3 = s3save, src = srcsave; --s3 >= 0; src = src->prev) {
2647 argsize -= IS_2_WORD_TYPE(src->type) ? 2 : 1;
2648 if (IS_FLT_DBL_TYPE(src->type))
2650 if (src->varkind == ARGVAR)
2652 if (IS_INT_LNG_TYPE(src->type)) {
2653 if (argsize < INT_ARG_CNT) {
2654 s1 = rd->argintregs[argsize];
2655 var_to_reg_int(d, src, s1);
2656 if (argsize < INT_ARG_CNT-1) {
2657 M_TINTMOVE(src->type, d, s1);
2661 if (IS_2_WORD_TYPE(src->type))
2662 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2666 var_to_reg_int(d, src, REG_ITMP1);
2667 M_IST(d, REG_SP, 4 * (argsize + 6));
2668 if (IS_2_WORD_TYPE(src->type))
2669 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2673 if (fltcnt < FLT_ARG_CNT) {
2674 s1 = rd->argfltregs[fltcnt];
2675 var_to_reg_flt(d, src, s1);
2679 var_to_reg_flt(d, src, REG_FTMP1);
2680 if (IS_2_WORD_TYPE(src->type))
2681 M_DST(d, REG_SP, 4 * (argsize + 6));
2683 M_FST(d, REG_SP, 4 * (argsize + 6));
2690 switch (iptr->opc) {
2694 a = dseg_addaddress(cd, (void *) lm);
2696 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2698 goto makeactualcall;
2700 case ICMD_INVOKESTATIC:
2701 case ICMD_INVOKESPECIAL:
2702 a = dseg_addaddress(cd, lm->stubroutine);
2704 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
2707 goto makeactualcall;
2709 case ICMD_INVOKEVIRTUAL:
2711 gen_nullptr_check(rd->argintregs[0]);
2712 M_ALD(REG_METHODPTR, rd->argintregs[0],
2713 OFFSET(java_objectheader, vftbl));
2714 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) +
2715 sizeof(methodptr) * lm->vftblindex);
2718 goto makeactualcall;
2720 case ICMD_INVOKEINTERFACE:
2723 gen_nullptr_check(rd->argintregs[0]);
2724 M_ALD(REG_METHODPTR, rd->argintregs[0],
2725 OFFSET(java_objectheader, vftbl));
2726 M_ALD(REG_METHODPTR, REG_METHODPTR,
2727 OFFSET(vftbl_t, interfacetable[0]) -
2728 sizeof(methodptr*) * ci->index);
2729 M_ALD(REG_PV, REG_METHODPTR,
2730 sizeof(methodptr) * (lm - ci->methods));
2733 goto makeactualcall;
2737 error ("Unkown ICMD-Command: %d", iptr->opc);
2746 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2748 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2750 s4 ml = -s1, mh = 0;
2751 while (ml < -32768) { ml += 65536; mh--; }
2752 M_LDA(REG_PV, REG_ITMP1, ml);
2753 M_LDAH(REG_PV, REG_PV, mh);
2756 /* d contains return type */
2758 if (d != TYPE_VOID) {
2759 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2760 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2761 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2762 store_reg_to_var_int(iptr->dst, s1);
2765 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2766 M_FLTMOVE(REG_FRESULT, s1);
2767 store_reg_to_var_flt(iptr->dst, s1);
2774 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2776 /* op1: 0 == array, 1 == class */
2777 /* val.a: (classinfo*) superclass */
2779 /* superclass is an interface:
2781 * return (sub != NULL) &&
2782 * (sub->vftbl->interfacetablelength > super->index) &&
2783 * (sub->vftbl->interfacetable[-super->index] != NULL);
2785 * superclass is a class:
2787 * return ((sub != NULL) && (0
2788 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2789 * super->vftbl->diffvall));
2793 classinfo *super = (classinfo*) iptr->val.a;
2795 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2796 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2798 var_to_reg_int(s1, src, REG_ITMP1);
2799 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2801 M_MOV(s1, REG_ITMP1);
2805 if (iptr->op1) { /* class/interface */
2807 if (super->flags & ACC_INTERFACE) { /* interface */
2809 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2810 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2811 M_LDATST(REG_ITMP2, REG_ITMP2, - super->index);
2813 M_ALD(REG_ITMP1, REG_ITMP1,
2814 OFFSET(vftbl_t, interfacetable[0]) -
2815 super->index * sizeof(methodptr*));
2819 M_IADD_IMM(REG_ZERO, 1, d);
2823 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2824 a = dseg_addaddress(cd, (void*) super->vftbl);
2825 M_ALD(REG_ITMP2, REG_PV, a);
2826 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2827 codegen_threadcritstart(cd, (u1*) mcodeptr - cd->mcodebase);
2829 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2830 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2831 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2832 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2833 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2835 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2836 M_CMPU(REG_ITMP1, REG_ITMP2);
2839 M_IADD_IMM(REG_ZERO, 1, d);
2843 panic ("internal error: no inlined array instanceof");
2845 store_reg_to_var_int(iptr->dst, d);
2848 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2850 /* op1: 0 == array, 1 == class */
2851 /* val.a: (classinfo*) superclass */
2853 /* superclass is an interface:
2855 * OK if ((sub == NULL) ||
2856 * (sub->vftbl->interfacetablelength > super->index) &&
2857 * (sub->vftbl->interfacetable[-super->index] != NULL));
2859 * superclass is a class:
2861 * OK if ((sub == NULL) || (0
2862 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2863 * super->vftbl->diffvall));
2867 classinfo *super = (classinfo*) iptr->val.a;
2869 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2870 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2872 var_to_reg_int(s1, src, REG_ITMP1);
2873 if (iptr->op1) { /* class/interface */
2875 if (super->flags & ACC_INTERFACE) { /* interface */
2877 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2878 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2879 M_LDATST(REG_ITMP3, REG_ITMP3, - super->index);
2881 codegen_addxcastrefs(cd, mcodeptr);
2882 M_ALD(REG_ITMP3, REG_ITMP2,
2883 OFFSET(vftbl_t, interfacetable[0]) -
2884 super->index * sizeof(methodptr*));
2887 codegen_addxcastrefs(cd, mcodeptr);
2890 M_BEQ(8 + (s1 == REG_ITMP1));
2891 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2892 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2893 codegen_threadcritstart(cd, (u1*) mcodeptr - cd->mcodebase);
2895 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2896 a = dseg_addaddress(cd, (void*) super->vftbl);
2897 M_ALD(REG_ITMP2, REG_PV, a);
2898 if (s1 != REG_ITMP1) {
2899 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2900 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2901 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2902 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2904 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2907 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2908 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2909 M_ALD(REG_ITMP2, REG_PV, a);
2910 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2911 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2912 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2915 M_CMPU(REG_ITMP3, REG_ITMP2);
2917 codegen_addxcastrefs(cd, mcodeptr);
2921 panic ("internal error: no inlined array checkcast");
2923 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2925 store_reg_to_var_int(iptr->dst, d);
2928 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
2930 var_to_reg_int(s1, src, REG_ITMP1);
2933 codegen_addxcheckarefs(cd, mcodeptr);
2936 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
2938 M_CMPI(REG_RESULT, 0);
2940 codegen_addxexceptionrefs(cd, mcodeptr);
2943 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2944 /* op1 = dimension, val.a = array descriptor */
2946 /* check for negative sizes and copy sizes to stack if necessary */
2948 MCODECHECK((iptr->op1 << 1) + 64);
2950 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
2951 var_to_reg_int(s2, src, REG_ITMP1);
2954 codegen_addxcheckarefs(cd, mcodeptr);
2956 /* copy SAVEDVAR sizes to stack */
2958 if (src->varkind != ARGVAR) {
2959 M_IST(s2, REG_SP, (s1 + INT_ARG_CNT + 6) * 4);
2963 /* a0 = dimension count */
2965 ICONST(rd->argintregs[0], iptr->op1);
2967 /* a1 = arraydescriptor */
2969 a = dseg_addaddress(cd, iptr->val.a);
2970 M_ALD(rd->argintregs[1], REG_PV, a);
2972 /* a2 = pointer to dimensions = stack pointer */
2974 M_LDA(rd->argintregs[2], REG_SP, (INT_ARG_CNT + 6) * 4);
2976 a = dseg_addaddress(cd, (void *) builtin_nmultianewarray);
2977 M_ALD(REG_PV, REG_PV, a);
2980 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2983 M_LDA (REG_PV, REG_ITMP1, -s1);
2985 s4 ml = -s1, mh = 0;
2986 while (ml < -32768) {ml += 65536; mh--;}
2987 M_LDA(REG_PV, REG_ITMP1, ml);
2988 M_LDAH(REG_PV, REG_PV, mh);
2990 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2991 M_INTMOVE(REG_RESULT, s1);
2992 store_reg_to_var_int(iptr->dst, s1);
2996 default: error ("Unknown pseudo command: %d", iptr->opc);
3000 } /* for instruction */
3002 /* copy values to interface registers */
3004 src = bptr->outstack;
3005 len = bptr->outdepth;
3006 MCODECHECK(64 + len);
3012 if ((src->varkind != STACKVAR)) {
3014 if (IS_FLT_DBL_TYPE(s2)) {
3015 var_to_reg_flt(s1, src, REG_FTMP1);
3016 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3017 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3020 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3024 var_to_reg_int(s1, src, REG_ITMP1);
3025 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3026 M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3029 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3030 if (IS_2_WORD_TYPE(s2))
3031 M_IST(rd->secondregs[s1], REG_SP, rd->interfaces[len][s2].regoff * 4 + 4);
3037 } /* if (bptr -> flags >= BBREACHED) */
3038 } /* for basic block */
3040 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3043 /* generate bound check stubs */
3045 s4 *xcodeptr = NULL;
3048 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3049 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3051 (u1 *) mcodeptr - cd->mcodebase);
3055 /* move index register into REG_ITMP1 */
3056 M_MOV(bref->reg, REG_ITMP1);
3057 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3059 if (xcodeptr != NULL) {
3060 M_BR(xcodeptr - mcodeptr - 1);
3063 xcodeptr = mcodeptr;
3065 M_STWU(REG_SP, REG_SP, -(24 + 2 * 4));
3066 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3068 M_MOV(REG_ITMP1, rd->argintregs[0]);
3070 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3071 M_ALD(REG_ITMP2, REG_PV, a);
3074 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3076 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3077 M_IADD_IMM(REG_SP, 24 + 2 * 4, REG_SP);
3079 a = dseg_addaddress(cd, asm_handle_exception);
3080 M_ALD(REG_ITMP3, REG_PV, a);
3087 /* generate negative array size check stubs */
3091 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3092 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3093 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3095 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3099 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3101 (u1 *) mcodeptr - cd->mcodebase);
3105 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3107 if (xcodeptr != NULL) {
3108 M_BR(xcodeptr - mcodeptr - 1);
3111 xcodeptr = mcodeptr;
3113 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3114 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3116 a = dseg_addaddress(cd, new_negativearraysizeexception);
3117 M_ALD(REG_ITMP2, REG_PV, a);
3120 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3122 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3123 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3125 a = dseg_addaddress(cd, asm_handle_exception);
3126 M_ALD(REG_ITMP3, REG_PV, a);
3133 /* generate cast check stubs */
3137 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3138 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3139 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3141 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3145 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3147 (u1 *) mcodeptr - cd->mcodebase);
3151 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3153 if (xcodeptr != NULL) {
3154 M_BR(xcodeptr - mcodeptr - 1);
3157 xcodeptr = mcodeptr;
3159 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3160 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3162 a = dseg_addaddress(cd, new_classcastexception);
3163 M_ALD(REG_ITMP2, REG_PV, a);
3166 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3168 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3169 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3171 a = dseg_addaddress(cd, asm_handle_exception);
3172 M_ALD(REG_ITMP3, REG_PV, a);
3179 /* generate exception check stubs */
3183 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3184 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3185 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3187 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3191 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3193 (u1 *) mcodeptr - cd->mcodebase);
3197 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3199 if (xcodeptr != NULL) {
3200 M_BR(xcodeptr - mcodeptr - 1);
3203 xcodeptr = mcodeptr;
3205 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3206 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3208 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3209 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3210 M_ALD(REG_ITMP2, REG_PV, a);
3214 /* get the exceptionptr from the ptrprt and clear it */
3215 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3217 M_AST(REG_ITMP3, REG_RESULT, 0);
3219 a = dseg_addaddress(cd, &_exceptionptr);
3220 M_ALD(REG_ITMP2, REG_PV, a);
3222 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);
3224 M_AST(REG_ITMP3, REG_ITMP2, 0);
3227 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3228 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3230 a = dseg_addaddress(cd, asm_handle_exception);
3231 M_ALD(REG_ITMP3, REG_PV, a);
3237 /* generate null pointer check stubs */
3241 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3242 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3243 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3245 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3249 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3251 (u1 *) mcodeptr - cd->mcodebase);
3255 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3257 if (xcodeptr != NULL) {
3258 M_BR(xcodeptr - mcodeptr - 1);
3261 xcodeptr = mcodeptr;
3263 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3264 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3266 a = dseg_addaddress(cd, new_nullpointerexception);
3267 M_ALD(REG_ITMP2, REG_PV, a);
3270 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3272 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3273 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3275 a = dseg_addaddress(cd, asm_handle_exception);
3276 M_ALD(REG_ITMP3, REG_PV, a);
3283 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
3285 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3289 /* function createcompilerstub *************************************************
3291 creates a stub routine which calls the compiler
3293 *******************************************************************************/
3295 #define COMPSTUBSIZE 6
3297 u1 *createcompilerstub(methodinfo *m)
3299 s4 *s = CNEW (s4, COMPSTUBSIZE); /* memory to hold the stub */
3300 s4 *mcodeptr = s; /* code generation pointer */
3302 M_LDA(REG_ITMP1, REG_PV, 4*4);
3303 M_ALD(REG_PV, REG_PV, 5*4);
3307 s[4] = (s4) m; /* literals to be adressed */
3308 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3310 asm_cacheflush((void*) s, (u1*) mcodeptr - (u1*) s);
3312 #if defined(STATISTICS)
3314 count_cstub_len += COMPSTUBSIZE * 4;
3321 /* function removecompilerstub *************************************************
3323 deletes a compilerstub from memory (simply by freeing it)
3325 *******************************************************************************/
3327 void removecompilerstub(u1 *stub)
3329 CFREE(stub, COMPSTUBSIZE * 4);
3333 /* function: createnativestub **************************************************
3335 creates a stub routine which calls a native method
3337 *******************************************************************************/
3339 #define NATIVESTUB_SIZE 200
3340 #define NATIVESTUB_OFFSET 9
3343 u1 *createnativestub(functionptr f, methodinfo *m)
3345 s4 *s; /* memory to hold the stub */
3348 s4 *mcodeptr; /* code generation pointer */
3349 s4 stackframesize = 0; /* size of stackframe if needed */
3352 t_inlining_globals *id;
3356 /* mark start of dump memory area */
3358 dumpsize = dump_size();
3360 /* setup registers before using it */
3362 rd = DNEW(registerdata);
3363 id = DNEW(t_inlining_globals);
3365 inlining_setup(m, id);
3366 reg_setup(m, rd, id);
3368 method_descriptor2types(m); /* set paramcount and paramtypes */
3370 stubsize = NATIVESTUB_SIZE; /* calculate nativestub size */
3372 s = CNEW(s4, stubsize);
3373 cs = s + NATIVESTUB_OFFSET;
3376 *(cs-1) = (u4) f; /* address of native method */
3377 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3378 *(cs-2) = (u4) builtin_get_exceptionptrptr;
3380 *(cs-2) = (u4) (&_exceptionptr); /* address of exceptionptr */
3382 *(cs-3) = (u4) asm_handle_nat_exception; /* addr of asm exception handler */
3383 *(cs-4) = (u4) (&env); /* addr of jni_environement */
3384 *(cs-5) = (u4) builtin_trace_args;
3386 *(cs-7) = (u4) builtin_displaymethodstop;
3387 *(cs-8) = (u4) m->class;
3388 *(cs-9) = (u4) asm_check_clinit;
3391 M_AST(REG_ITMP1, REG_SP, 8); /* store return address */
3392 /* Build up new Stackframe for native call */
3393 stackframesize = 24; /* 24 Bytes Linkage Area */
3394 stackframesize += (m->flags & ACC_STATIC) ? 8 : 4; /*1 or 2 additional int parameters */
3395 for (i = 0; i < m->paramcount; i++) {
3396 stackframesize += IS_2_WORD_TYPE(m->paramtypes[i]) ? 8 : 4;
3399 if (stackframesize < (24+32)) { /* 24 Byte Linkage Area + 32 Bytes minimum Argument area */
3400 stackframesize = 24+32;
3402 stackframesize = stackframesize + 8; /* Reserve Space to store Result registers */
3403 stackframesize = (stackframesize + 3) & ~3; /* Keep Stack 16 Byte aligned */
3404 M_STWU(REG_SP, REG_SP, -stackframesize); /* build up stackframe */
3406 /* if function is static, check for initialized */
3408 if (m->flags & ACC_STATIC) {
3409 /* if class isn't yet initialized, do it */
3410 if (!m->class->initialized) {
3411 /* call helper function which patches this code */
3412 M_ALD(REG_ITMP1, REG_PV, -8 * 4); /* class */
3413 M_ALD(REG_PV, REG_PV, -9 * 4); /* asm_check_clinit */
3416 disp = -(s4) (mcodeptr - cs) * 4;
3418 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3428 /* M_MFLR(REG_ITMP3); */
3429 /* XXX must be a multiple of 16 */
3430 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
3432 /* M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3436 /* save all arguments into the reserved stack space */
3437 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3438 t = m->paramtypes[p];
3440 if (IS_INT_LNG_TYPE(t)) {
3441 /* overlapping u8's are on the stack */
3442 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
3443 s1 = rd->argintregs[p + longargs + dblargs];
3445 if (!IS_2_WORD_TYPE(t)) {
3446 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3447 M_IST(s1, REG_SP, 24 + p * 8 + 4);
3450 M_IST(s1, REG_SP, 24 + p * 8);
3451 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3456 /* we do not have a data segment here */
3457 /* a = dseg_adds4(cd, 0xdeadbeef);
3458 M_ILD(REG_ITMP1, REG_PV, a); */
3459 M_LDA(REG_ITMP1, REG_ZERO, -1);
3460 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3461 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
3465 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3466 s1 = rd->argfltregs[fltargs + dblargs];
3468 if (!IS_2_WORD_TYPE(t)) {
3469 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3470 M_FST(s1, REG_SP, 24 + p * 8 + 4);
3474 M_DST(s1, REG_SP, 24 + p * 8);
3479 /* this should not happen */
3484 /* TODO: save remaining integer and flaot argument registers */
3486 /* load first 4 arguments into integer argument registers */
3487 for (p = 0; p < 8; p++) {
3488 d = rd->argintregs[p];
3489 M_ILD(d, REG_SP, 24 + p * 4);
3492 M_ALD(REG_ITMP1, REG_PV, -6 * 4);
3493 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
3494 M_ALD(REG_ITMP2, REG_PV, -5 * 4);
3502 /* restore arguments into the reserved stack space */
3503 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3504 t = m->paramtypes[p];
3506 if (IS_INT_LNG_TYPE(t)) {
3507 if ((p + longargs + dblargs) < INT_ARG_CNT) {
3508 s1 = rd->argintregs[p + longargs + dblargs];
3510 if (!IS_2_WORD_TYPE(t)) {
3511 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
3514 M_ILD(s1, REG_SP, 24 + p * 8);
3515 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3521 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3522 s1 = rd->argfltregs[fltargs + dblargs];
3524 if (!IS_2_WORD_TYPE(t)) {
3525 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
3529 M_DLD(s1, REG_SP, 24 + p * 8);
3536 /* M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3538 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
3539 /* M_MTLR(REG_ITMP3); */
3542 /* save argument registers on stack -- if we have to */
3543 /* and copy spilled argument regs from old stack to the new one */
3552 shift = (m->flags & ACC_STATIC) ? 2 : 1;
3553 for (i = 0; i < m->paramcount; i++) {
3554 paramsize = IS_2_WORD_TYPE(m->paramtypes[i]) ? 2 : 1;
3555 if (IS_FLT_DBL_TYPE(m->paramtypes[i])) {
3557 if (farg >= FLT_ARG_CNT) { /* spilled float arg -> copy from old stack */
3558 if (paramsize == 1) { /* float arg */
3559 M_FLD(REG_FTMP1, REG_SP, stackframesize + 24 + 4 * stack_off);
3560 M_FST(REG_FTMP1, REG_SP, 24 + 4*(shift + stack_off));
3561 } else { /* double arg */
3562 M_DLD(REG_FTMP1, REG_SP, stackframesize + 24 + 4 * stack_off);
3563 M_DST(REG_FTMP1, REG_SP, 24 + 4*(shift + stack_off));
3566 } else { /* int arg */
3567 iarg = stack_off; /* int register are not consecutive like the float*/
3568 if (iarg + paramsize -1 < INT_ARG_CNT) {
3569 if ( iarg + paramsize -1 == INT_ARG_CNT - shift ) {
3570 /* int arg reg(s) spilled through shift to stack */
3571 M_IST( rd->argintregs[iarg], REG_SP, 24 + 4 * (shift + stack_off));
3572 if (paramsize == 2) /* spill secondreg, too */
3573 M_IST( rd->argintregs[iarg+1], REG_SP, 24 + 4 * (shift + stack_off) + 4);
3575 } else { /* already spilled int arg -> copy from old stack */
3576 M_ILD(REG_ITMP1, REG_SP, stackframesize + 24 + 4 * stack_off);
3577 M_IST(REG_ITMP1, REG_SP, 24 + 4 * (shift + stack_off));
3578 if (paramsize == 2) { /* long arg -> copy second half, too */
3579 M_ILD(REG_ITMP1, REG_SP, stackframesize + 24 + 4 * stack_off + 4);
3580 M_IST(REG_ITMP1, REG_SP, 24 + 4*(shift + stack_off) + 4);
3584 stack_off += paramsize;
3587 /* now shift integer argument registers */
3588 for (i = m->paramcount - 1; i >=0; i--) {
3589 paramsize = IS_2_WORD_TYPE(m->paramtypes[i]) ? 2 : 1;
3590 stack_off -= paramsize;
3591 if (IS_INT_LNG_TYPE(m->paramtypes[i])) {
3593 if ( iarg + paramsize -1 < INT_ARG_CNT - shift ) {
3594 /* shift integer arg */
3596 M_MOV(rd->argintregs[iarg+1], rd->argintregs[iarg + shift + 1]);
3597 M_MOV(rd->argintregs[iarg], rd->argintregs[iarg + shift]);
3598 } /* else are already spilled to memory */
3603 if (m->flags & ACC_STATIC)
3604 /* put class into second argument register */
3605 M_ALD(rd->argintregs[1], REG_PV, -8 * 4);
3607 /* put env into first argument register */
3608 M_ALD(rd->argintregs[0], REG_PV, -4 * 4);
3610 M_ALD(REG_PV, REG_PV, -1 * 4); /* load adress of native method */
3613 disp = -(s4) (mcodeptr - cs) * 4;
3615 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3617 /* 20 instructions */
3620 M_LDA(REG_SP, REG_SP, -10 * 8);
3621 M_DST(REG_FRESULT, REG_SP, 48+0);
3622 M_IST(REG_RESULT, REG_SP, 48+8);
3623 M_AST(REG_ITMP3, REG_SP, 48+12);
3624 M_IST(REG_RESULT2, REG_SP, 48+16);
3626 /* keep this order */
3627 switch (m->returntype) {
3630 M_MOV(REG_RESULT, rd->argintregs[2]);
3631 M_CLR(rd->argintregs[1]);
3635 M_MOV(REG_RESULT2, rd->argintregs[2]);
3636 M_MOV(REG_RESULT, rd->argintregs[1]);
3639 M_ALD(rd->argintregs[0], REG_PV, -6 * 4);
3641 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
3642 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
3643 M_ALD(REG_ITMP2, REG_PV, -7 * 4);/* builtin_displaymethodstop */
3646 M_DLD(REG_FRESULT, REG_SP, 48+0);
3647 M_ILD(REG_RESULT, REG_SP, 48+8);
3648 M_ALD(REG_ITMP3, REG_SP, 48+12);
3649 M_ILD(REG_RESULT2, REG_SP, 48+16);
3650 M_LDA(REG_SP, REG_SP, 10 * 8);
3654 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3655 if (IS_FLT_DBL_TYPE(m->returntype))
3656 if (IS_2_WORD_TYPE(m->returntype))
3657 M_DST(REG_FRESULT, REG_SP, stackframesize-8 /*56*/);
3659 M_FST(REG_FRESULT, REG_SP, stackframesize-8 /*56*/);
3661 M_IST(REG_RESULT, REG_SP, stackframesize-8 /*56*/);
3662 if (IS_2_WORD_TYPE(m->returntype))
3663 M_IST(REG_RESULT2, REG_SP, stackframesize-4 /* 60*/);
3666 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* builtin_get_exceptionptrptr */
3669 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3671 M_LDA(REG_PV, REG_ITMP1, disp);
3672 M_MOV(REG_RESULT, REG_ITMP2);
3674 if (IS_FLT_DBL_TYPE(m->returntype))
3675 if (IS_2_WORD_TYPE(m->returntype))
3676 M_DLD(REG_FRESULT, REG_SP, stackframesize-8 /*56*/);
3678 M_FLD(REG_FRESULT, REG_SP, stackframesize-8 /*56*/);
3680 M_ILD(REG_RESULT, REG_SP, stackframesize-8 /*56*/);
3681 if (IS_2_WORD_TYPE(m->returntype))
3682 M_ILD(REG_RESULT2, REG_SP, stackframesize-4 /*60*/);
3685 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* get address of exceptionptr */
3687 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);/* load exception into reg. itmp1 */
3688 M_TST(REG_ITMP1_XPTR);
3689 M_BNE(4); /* if no exception then return */
3691 M_ALD(REG_ITMP1, REG_SP, stackframesize + 8); /* load return address */
3693 M_LDA(REG_SP, REG_SP, stackframesize); /* remove stackframe */
3698 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
3700 M_ALD(REG_ITMP2, REG_SP, stackframesize + 8); /* load return address */
3703 M_LDA(REG_SP, REG_SP, stackframesize); /* remove stackframe */
3705 M_IADD_IMM(REG_ITMP2, -4, REG_ITMP2_XPC); /* fault address */
3707 M_ALD(REG_ITMP3, REG_PV, -3 * 4); /* load asm exception handler address */
3711 /* Check if the stub size is big enough to hold the whole stub generated. */
3712 /* If not, this can lead into unpredictable crashes, because of heap */
3714 if ((s4) (mcodeptr - s) > stubsize) {
3715 throw_cacao_exception_exit(string_java_lang_InternalError,
3716 "Native stub size %d is to small for current stub size %d",
3717 stubsize, (s4) (mcodeptr - s));
3720 asm_cacheflush((void *) s, (u1*) mcodeptr - (u1*) s);
3722 #if defined(STATISTICS)
3724 count_nstub_len += NATIVESTUB_SIZE * 4;
3727 /* release dump area */
3729 dump_release(dumpsize);
3731 return (u1*) (s + NATIVESTUB_OFFSET);
3735 /* function: removenativestub **************************************************
3737 removes a previously created native-stub from memory
3739 *******************************************************************************/
3741 void removenativestub(u1 *stub)
3743 CFREE((s4 *) stub - NATIVESTUB_OFFSET, NATIVESTUB_SIZE * 4);
3748 * These are local overrides for various environment variables in Emacs.
3749 * Please do not remove this and leave it at the end of the file, where
3750 * Emacs will automagically detect them.
3751 * ---------------------------------------------------------------------
3754 * indent-tabs-mode: t