1 /* src/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 2525 2005-05-24 10:28:20Z twisti $
42 #include "cacao/cacao.h"
43 #include "native/native.h"
44 #include "vm/builtin.h"
45 #include "vm/global.h"
46 #include "vm/loader.h"
47 #include "vm/stringlocal.h"
48 #include "vm/tables.h"
49 #include "vm/jit/asmpart.h"
50 #include "vm/jit/jit.h"
51 #include "vm/jit/parse.h"
52 #include "vm/jit/patcher.h"
53 #include "vm/jit/reg.h"
54 #include "vm/jit/powerpc/arch.h"
55 #include "vm/jit/powerpc/codegen.h"
56 #include "vm/jit/powerpc/types.h"
59 /* register descripton - array ************************************************/
61 /* #define REG_RES 0 reserved register for OS or code generator */
62 /* #define REG_RET 1 return value register */
63 /* #define REG_EXC 2 exception value register (only old jit) */
64 /* #define REG_SAV 3 (callee) saved register */
65 /* #define REG_TMP 4 scratch temporary register (caller saved) */
66 /* #define REG_ARG 5 argument register (caller saved) */
68 /* #define REG_END -1 last entry in tables */
70 static int nregdescint[] = {
71 REG_RES, REG_RES, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
72 REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV,
73 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
74 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
77 /* for use of reserved registers, see comment above */
79 static int nregdescfloat[] = {
80 REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
81 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV,
82 REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
83 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
87 /* Include independent code generation stuff -- include after register */
88 /* descriptions to avoid extern definitions. */
90 #include "vm/jit/codegen.inc"
91 #include "vm/jit/reg.inc"
93 #include "vm/jit/lsra.inc"
97 void asm_cacheflush(void *, long);
99 /* #include <architecture/ppc/cframe.h> */
101 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
102 void thread_restartcriticalsection(void *u)
104 /* XXX set pc to restart address */
108 #if defined(__DARWIN__)
109 #include <mach/message.h>
111 int cacao_catch_Handler(mach_port_t thread)
113 #if defined(USE_THREADS)
115 unsigned int crashpc;
117 java_objectheader *xptr;
120 thread_state_flavor_t flavor = PPC_THREAD_STATE;
121 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
122 ppc_thread_state_t thread_state;
128 r = thread_get_state(thread, flavor,
129 (natural_t*)&thread_state, &thread_state_count);
130 if (r != KERN_SUCCESS) {
131 log_text("thread_get_state failed");
135 regs = &thread_state.r0;
136 crashpc = thread_state.srr0;
138 instr = *(s4*) crashpc;
139 reg = (instr >> 16) & 31;
142 /* This is now handled in asmpart because it needs to run in the throwing
144 /* xptr = new_nullpointerexception(); */
146 regs[REG_ITMP2_XPC] = crashpc;
147 /* regs[REG_ITMP1_XPTR] = (u4) xptr; */
148 thread_state.srr0 = (u4) asm_handle_nullptr_exception;
150 r = thread_set_state(thread, flavor,
151 (natural_t*)&thread_state, thread_state_count);
152 if (r != KERN_SUCCESS) {
153 log_text("thread_set_state failed");
160 throw_cacao_exception_exit(string_java_lang_InternalError,
161 "Segmentation fault at %p", regs[reg]);
166 #endif /* __DARWIN__ */
169 void init_exceptions(void)
173 #if !defined(__DARWIN__)
174 nregdescint[2] = REG_RES;
178 void adjust_argvars(stackptr s, int d, int *fa, int *ia)
184 adjust_argvars(s->prev, d-1, fa, ia);
185 if (s->varkind == ARGVAR)
186 s->varnum = (IS_FLT_DBL_TYPE(s->type)) ? *fa : *ia;
187 *fa += (IS_FLT_DBL_TYPE(s->type) != 0);
188 *ia += (IS_2_WORD_TYPE(s->type)) ? 2 : 1;
192 #define intmaxf(a,b) (((a)<(b)) ? (b) : (a))
194 void preregpass(methodinfo *m, registerdata *rd)
204 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
206 for (iptr = bptr->iinstr, src = bptr->instack;
208 src = iptr->dst, len--, iptr++)
210 if (bptr->flags < BBREACHED)
223 case ICMD_INVOKEVIRTUAL:
224 case ICMD_INVOKESPECIAL:
225 case ICMD_INVOKESTATIC:
226 case ICMD_INVOKEINTERFACE:
231 adjust_argvars(src, s3, &fa, &ia);
234 for (; --s3 >= 0; src = src->prev) {
235 paramsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
237 rd->ifmemuse = intmaxf(rd->ifmemuse, paramsize);
240 case ICMD_MULTIANEWARRAY:
242 paramsize = rd->intreg_argnum + s3;
243 rd->ifmemuse = intmaxf(rd->ifmemuse, paramsize);
250 rd->maxmemuse = rd->ifmemuse;
254 /* function gen_mcode **********************************************************
256 generates machine code
258 *******************************************************************************/
260 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
262 s4 len, s1, s2, s3, d;
278 /* space to save used callee saved registers */
280 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
281 savedregs_num += 2 * (rd->savfltregcnt - rd->maxsavfltreguse);
283 parentargs_base = rd->maxmemuse + savedregs_num;
285 #ifdef USE_THREADS /* space to save argument of monitor_enter */
286 /* and Return Values to survive monitor_exit */
287 if (checksync && (m->flags & ACC_SYNCHRONIZED))
292 /* create method header */
294 parentargs_base = (parentargs_base + 3) & ~3;
297 (void) dseg_addaddress(cd, m); /* Filler */
299 (void) dseg_addaddress(cd, m); /* MethodPointer */
300 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
304 /* IsSync contains the offset relative to the stack pointer for the
305 argument of monitor_exit used in the exception handler. Since the
306 offset could be zero and give a wrong meaning of the flag it is
310 if (checksync && (m->flags & ACC_SYNCHRONIZED))
311 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 4); /* IsSync */
316 (void) dseg_adds4(cd, 0); /* IsSync */
318 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
319 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
320 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
321 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
323 /* create exception table */
325 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
326 dseg_addtarget(cd, ex->start);
327 dseg_addtarget(cd, ex->end);
328 dseg_addtarget(cd, ex->handler);
329 (void) dseg_addaddress(cd, ex->catchtype.cls);
332 /* initialize mcode variables */
334 mcodeptr = (s4 *) cd->mcodebase;
335 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
336 MCODECHECK(128 + m->paramcount);
338 /* create stack frame (if necessary) */
340 if (!m->isleafmethod) {
342 M_AST(REG_ITMP3, REG_SP, 8);
345 if (parentargs_base) {
346 M_STWU(REG_SP, REG_SP, -parentargs_base * 4);
349 /* save return address and used callee saved registers */
352 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
353 p--; M_IST(rd->savintregs[i], REG_SP, 4 * p);
355 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
356 p-=2; M_DST(rd->savfltregs[i], REG_SP, 4 * p);
358 /* take arguments out of register or stack frame */
364 for (p = 0, l = 0; p < m->paramcount; p++) {
365 arg = narg; iarg = niarg;
366 t = m->paramtypes[p];
367 var = &(rd->locals[l][t]);
369 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
373 if (IS_INT_LNG_TYPE(t)) { /* integer args */
374 if (iarg < INT_ARG_CNT -
375 (IS_2_WORD_TYPE(t)!=0)) { /* register arguments */
376 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
377 M_TINTMOVE(t, rd->argintregs[iarg], var->regoff);
379 } else { /* reg arg -> spilled */
380 M_IST(rd->argintregs[iarg], REG_SP, 4 * var->regoff);
381 if (IS_2_WORD_TYPE(t))
382 M_IST(rd->secondregs[rd->argintregs[iarg]], REG_SP, 4 * var->regoff + 4);
385 } else { /* stack arguments */
387 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
388 M_ILD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
389 if (IS_2_WORD_TYPE(t))
390 M_ILD(rd->secondregs[var->regoff], REG_SP, 4 * (parentargs_base + pa) + 4);
392 } else { /* stack arg -> spilled */
393 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa));
394 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff);
395 if (IS_2_WORD_TYPE(t)) {
396 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa) + 4);
397 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff + 4);
402 } else { /* floating args */
404 if (arg < FLT_ARG_CNT) { /* register arguments */
405 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
406 M_FLTMOVE(rd->argfltregs[arg], var->regoff);
408 } else { /* reg arg -> spilled */
409 if (IS_2_WORD_TYPE(t))
410 M_DST(rd->argfltregs[arg], REG_SP, 4 * var->regoff);
412 M_FST(rd->argfltregs[arg], REG_SP, 4 * var->regoff);
415 } else { /* stack arguments */
417 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
418 if (IS_2_WORD_TYPE(t))
419 M_DLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
422 M_FLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
424 } else { /* stack-arg -> spilled */
425 if (IS_2_WORD_TYPE(t)) {
426 M_DLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
427 M_DST(REG_FTMP1, REG_SP, 4 * var->regoff);
430 M_FLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
431 M_FST(REG_FTMP1, REG_SP, 4 * var->regoff);
439 /* save monitorenter argument */
441 #if defined(USE_THREADS)
442 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
443 if (m->flags & ACC_STATIC) {
444 p = dseg_addaddress(cd, m->class);
445 M_ALD(REG_ITMP1, REG_PV, p);
446 M_AST(REG_ITMP1, REG_SP, 4 * rd->maxmemuse);
449 M_AST(rd->argintregs[0], REG_SP, 4 * rd->maxmemuse);
453 /* call monitorenter function */
455 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
456 s4 func_enter = (m->flags & ACC_STATIC) ?
457 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
458 p = dseg_addaddress(cd, (void *) func_enter);
459 M_ALD(REG_ITMP3, REG_PV, p);
461 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
467 /* copy argument registers to stack and call trace function with pointer
468 to arguments on stack.
477 /* XXX must be a multiple of 16 */
478 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
480 M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
482 M_CLR(REG_ITMP1); /* clear help register */
484 /* save all arguments into the reserved stack space */
485 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
486 t = m->paramtypes[p];
488 if (IS_INT_LNG_TYPE(t)) {
489 /* overlapping u8's are on the stack */
490 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
491 s1 = rd->argintregs[p + longargs + dblargs];
493 if (!IS_2_WORD_TYPE(t)) {
494 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
495 M_IST(s1, REG_SP, 24 + p * 8 + 4);
498 M_IST(s1, REG_SP, 24 + p * 8);
499 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
504 a = dseg_adds4(cd, 0xdeadbeef);
505 M_ILD(REG_ITMP1, REG_PV, a);
506 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
507 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
511 if ((fltargs + dblargs) < FLT_ARG_CNT) {
512 s1 = rd->argfltregs[fltargs + dblargs];
514 if (!IS_2_WORD_TYPE(t)) {
515 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
516 M_FST(s1, REG_SP, 24 + p * 8 + 4);
520 M_DST(s1, REG_SP, 24 + p * 8);
525 /* this should not happen */
530 /* TODO: save remaining integer and flaot argument registers */
532 /* load first 4 arguments into integer argument registers */
533 for (p = 0; p < 8; p++) {
534 d = rd->argintregs[p];
535 M_ILD(d, REG_SP, 24 + p * 4);
538 p = dseg_addaddress(cd, m);
539 M_ALD(REG_ITMP1, REG_PV, p);
540 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
541 p = dseg_addaddress(cd, (void *) builtin_trace_args);
542 M_ALD(REG_ITMP2, REG_PV, p);
550 /* restore arguments into the reserved stack space */
551 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
552 t = m->paramtypes[p];
554 if (IS_INT_LNG_TYPE(t)) {
555 if ((p + longargs + dblargs) < INT_ARG_CNT) {
556 s1 = rd->argintregs[p + longargs + dblargs];
558 if (!IS_2_WORD_TYPE(t)) {
559 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
562 M_ILD(s1, REG_SP, 24 + p * 8);
563 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
569 if ((fltargs + dblargs) < FLT_ARG_CNT) {
570 s1 = rd->argfltregs[fltargs + dblargs];
572 if (!IS_2_WORD_TYPE(t)) {
573 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
577 M_DLD(s1, REG_SP, 24 + p * 8);
584 M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
586 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
595 /* end of header generation */
597 /* walk through all basic blocks */
598 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
600 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
602 if (bptr->flags >= BBREACHED) {
604 /* branch resolving */
608 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
609 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
615 /* copy interface registers to their destination */
623 while (src != NULL) {
625 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
626 /* d = reg_of_var(m, src, REG_ITMP1); */
627 if (!(src->flags & INMEMORY))
631 M_INTMOVE(REG_ITMP1, d);
632 store_reg_to_var_int(src, d);
638 while (src != NULL) {
640 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
641 d = reg_of_var(rd, src, REG_ITMP1);
642 M_INTMOVE(REG_ITMP1, d);
643 store_reg_to_var_int(src, d);
646 d = reg_of_var(rd, src, REG_IFTMP);
647 if ((src->varkind != STACKVAR)) {
649 if (IS_FLT_DBL_TYPE(s2)) {
650 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
651 s1 = rd->interfaces[len][s2].regoff;
655 if (IS_2_WORD_TYPE(s2)) {
656 M_DLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
659 M_FLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
662 store_reg_to_var_flt(src, d);
665 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
666 s1 = rd->interfaces[len][s2].regoff;
670 M_ILD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
671 if (IS_2_WORD_TYPE(s2))
672 M_ILD(rd->secondregs[d], REG_SP, 4 * rd->interfaces[len][s2].regoff + 4);
674 store_reg_to_var_int(src, d);
684 /* walk through all instructions */
688 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
690 MCODECHECK(64); /* an instruction usually needs < 64 words */
692 case ICMD_NOP: /* ... ==> ... */
693 case ICMD_INLINE_START:
694 case ICMD_INLINE_END:
697 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
699 var_to_reg_int(s1, src, REG_ITMP1);
702 codegen_addxnullrefs(cd, mcodeptr);
705 /* constant operations ************************************************/
707 case ICMD_ICONST: /* ... ==> ..., constant */
708 /* op1 = 0, val.i = constant */
710 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
711 ICONST(d, iptr->val.i);
712 store_reg_to_var_int(iptr->dst, d);
715 case ICMD_LCONST: /* ... ==> ..., constant */
716 /* op1 = 0, val.l = constant */
718 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
719 LCONST(d, iptr->val.l);
720 store_reg_to_var_int(iptr->dst, d);
723 case ICMD_FCONST: /* ... ==> ..., constant */
724 /* op1 = 0, val.f = constant */
726 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
727 a = dseg_addfloat(cd, iptr->val.f);
729 store_reg_to_var_flt(iptr->dst, d);
732 case ICMD_DCONST: /* ... ==> ..., constant */
733 /* op1 = 0, val.d = constant */
735 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
736 a = dseg_adddouble(cd, iptr->val.d);
738 store_reg_to_var_flt(iptr->dst, d);
741 case ICMD_ACONST: /* ... ==> ..., constant */
742 /* op1 = 0, val.a = constant */
744 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
745 ICONST(d, (u4) iptr->val.a);
746 store_reg_to_var_int(iptr->dst, d);
750 /* load/store operations **********************************************/
752 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
753 case ICMD_LLOAD: /* op1 = local variable */
756 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
757 if ((iptr->dst->varkind == LOCALVAR) &&
758 (iptr->dst->varnum == iptr->op1))
760 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
761 if (var->flags & INMEMORY) {
762 M_ILD(d, REG_SP, 4 * var->regoff);
763 if (IS_2_WORD_TYPE(var->type))
764 M_ILD(rd->secondregs[d], REG_SP, 4 * var->regoff + 4);
766 M_TINTMOVE(var->type, var->regoff, d);
768 store_reg_to_var_int(iptr->dst, d);
771 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
772 case ICMD_DLOAD: /* op1 = local variable */
774 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
775 if ((iptr->dst->varkind == LOCALVAR) &&
776 (iptr->dst->varnum == iptr->op1))
778 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
779 if (var->flags & INMEMORY)
780 if (IS_2_WORD_TYPE(var->type))
781 M_DLD(d, REG_SP, 4 * var->regoff);
783 M_FLD(d, REG_SP, 4 * var->regoff);
785 M_FLTMOVE(var->regoff, d);
787 store_reg_to_var_flt(iptr->dst, d);
791 case ICMD_ISTORE: /* ..., value ==> ... */
792 case ICMD_LSTORE: /* op1 = local variable */
795 if ((src->varkind == LOCALVAR) &&
796 (src->varnum == iptr->op1))
798 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
799 if (var->flags & INMEMORY) {
800 var_to_reg_int(s1, src, REG_ITMP1);
801 M_IST(s1, REG_SP, 4 * var->regoff);
802 if (IS_2_WORD_TYPE(var->type))
803 M_IST(rd->secondregs[s1], REG_SP, 4 * var->regoff + 4);
805 var_to_reg_int(s1, src, var->regoff);
806 M_TINTMOVE(var->type, s1, var->regoff);
810 case ICMD_FSTORE: /* ..., value ==> ... */
811 case ICMD_DSTORE: /* op1 = local variable */
813 if ((src->varkind == LOCALVAR) &&
814 (src->varnum == iptr->op1))
816 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
817 if (var->flags & INMEMORY) {
818 var_to_reg_flt(s1, src, REG_FTMP1);
819 if (var->type == TYPE_DBL)
820 M_DST(s1, REG_SP, 4 * var->regoff);
822 M_FST(s1, REG_SP, 4 * var->regoff);
824 var_to_reg_flt(s1, src, var->regoff);
825 M_FLTMOVE(s1, var->regoff);
830 /* pop/dup/swap operations ********************************************/
832 /* attention: double and longs are only one entry in CACAO ICMDs */
834 case ICMD_POP: /* ..., value ==> ... */
835 case ICMD_POP2: /* ..., value, value ==> ... */
838 case ICMD_DUP: /* ..., a ==> ..., a, a */
839 M_COPY(src, iptr->dst);
842 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
844 M_COPY(src, iptr->dst);
845 M_COPY(src->prev, iptr->dst->prev);
846 M_COPY(iptr->dst, iptr->dst->prev->prev);
849 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
851 M_COPY(src, iptr->dst);
852 M_COPY(src->prev, iptr->dst->prev);
853 M_COPY(src->prev->prev, iptr->dst->prev->prev);
854 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
857 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
859 M_COPY(src, iptr->dst);
860 M_COPY(src->prev, iptr->dst->prev);
863 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
865 M_COPY(src, iptr->dst);
866 M_COPY(src->prev, iptr->dst->prev);
867 M_COPY(src->prev->prev, iptr->dst->prev->prev);
868 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
869 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
872 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
874 M_COPY(src, iptr->dst);
875 M_COPY(src->prev, iptr->dst->prev);
876 M_COPY(src->prev->prev, iptr->dst->prev->prev);
877 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
878 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
879 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
882 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
884 M_COPY(src, iptr->dst->prev);
885 M_COPY(src->prev, iptr->dst);
889 /* integer operations *************************************************/
891 case ICMD_INEG: /* ..., 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);
899 case ICMD_LNEG: /* ..., value ==> ..., - value */
901 var_to_reg_int(s1, src, REG_ITMP1);
902 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
903 M_SUBFIC(rd->secondregs[s1], 0, rd->secondregs[d]);
905 store_reg_to_var_int(iptr->dst, d);
908 case ICMD_I2L: /* ..., value ==> ..., value */
910 var_to_reg_int(s1, src, REG_ITMP2);
911 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
912 M_INTMOVE(s1, rd->secondregs[d]);
913 M_SRA_IMM(rd->secondregs[d], 31, d);
914 store_reg_to_var_int(iptr->dst, d);
917 case ICMD_L2I: /* ..., value ==> ..., value */
919 var_to_reg_int0(s1, src, REG_ITMP2, 0, 1);
920 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
922 store_reg_to_var_int(iptr->dst, d);
925 case ICMD_INT2BYTE: /* ..., 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_INT2CHAR: /* ..., 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);
941 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
943 var_to_reg_int(s1, src, REG_ITMP1);
944 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
946 store_reg_to_var_int(iptr->dst, d);
950 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
952 var_to_reg_int(s1, src->prev, REG_ITMP1);
953 var_to_reg_int(s2, src, REG_ITMP2);
954 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
956 store_reg_to_var_int(iptr->dst, d);
959 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
960 /* val.i = constant */
962 var_to_reg_int(s1, src, REG_ITMP1);
963 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
964 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
965 M_IADD_IMM(s1, iptr->val.i, d);
968 ICONST(REG_ITMP2, iptr->val.i);
969 M_IADD(s1, REG_ITMP2, d);
971 store_reg_to_var_int(iptr->dst, d);
974 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
976 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
977 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
978 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
979 M_ADDC(s1, s2, rd->secondregs[d]);
980 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
981 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
983 store_reg_to_var_int(iptr->dst, d);
986 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
987 /* val.l = constant */
989 s3 = iptr->val.l & 0xffffffff;
990 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
991 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
992 if ((s3 >= -32768) && (s3 <= 32767)) {
993 M_ADDIC(s1, s3, rd->secondregs[d]);
996 ICONST(REG_ITMP2, s3);
997 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
999 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1000 s3 = iptr->val.l >> 32;
1006 ICONST(REG_ITMP3, s3);
1007 M_ADDE(s1, REG_ITMP3, d);
1009 store_reg_to_var_int(iptr->dst, d);
1012 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1014 var_to_reg_int(s1, src->prev, REG_ITMP1);
1015 var_to_reg_int(s2, src, REG_ITMP2);
1016 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1018 store_reg_to_var_int(iptr->dst, d);
1021 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1022 /* val.i = constant */
1024 var_to_reg_int(s1, src, REG_ITMP1);
1025 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1026 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
1027 M_IADD_IMM(s1, -iptr->val.i, d);
1030 ICONST(REG_ITMP2, -iptr->val.i);
1031 M_IADD(s1, REG_ITMP2, d);
1033 store_reg_to_var_int(iptr->dst, d);
1036 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1038 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1039 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1040 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1041 M_SUBC(s1, s2, rd->secondregs[d]);
1042 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1043 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1045 store_reg_to_var_int(iptr->dst, d);
1048 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1049 /* val.l = constant */
1051 s3 = (-iptr->val.l) & 0xffffffff;
1052 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1053 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1054 if ((s3 >= -32768) && (s3 <= 32767)) {
1055 M_ADDIC(s1, s3, rd->secondregs[d]);
1058 ICONST(REG_ITMP2, s3);
1059 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
1061 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1062 s3 = (-iptr->val.l) >> 32;
1068 ICONST(REG_ITMP3, s3);
1069 M_ADDE(s1, REG_ITMP3, d);
1071 store_reg_to_var_int(iptr->dst, d);
1074 case ICMD_IDIV: /* ..., 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);
1079 store_reg_to_var_int(iptr->dst, d);
1082 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1083 var_to_reg_int(s1, src->prev, REG_ITMP1);
1084 var_to_reg_int(s2, src, REG_ITMP2);
1085 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1089 store_reg_to_var_int(iptr->dst, d);
1092 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1094 var_to_reg_int(s1, src->prev, REG_ITMP1);
1095 var_to_reg_int(s2, src, REG_ITMP2);
1096 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1098 store_reg_to_var_int(iptr->dst, d);
1101 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1102 /* val.i = constant */
1104 var_to_reg_int(s1, src, REG_ITMP1);
1105 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1106 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1107 M_IMUL_IMM(s1, iptr->val.i, d);
1110 ICONST(REG_ITMP2, iptr->val.i);
1111 M_IMUL(s1, REG_ITMP2, d);
1113 store_reg_to_var_int(iptr->dst, d);
1116 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1118 var_to_reg_int(s1, src, REG_ITMP1);
1119 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1120 M_SRA_IMM(s1, iptr->val.i, d);
1122 store_reg_to_var_int(iptr->dst, d);
1125 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1127 var_to_reg_int(s1, src->prev, REG_ITMP1);
1128 var_to_reg_int(s2, src, REG_ITMP2);
1129 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1130 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1131 M_SLL(s1, REG_ITMP3, d);
1132 store_reg_to_var_int(iptr->dst, d);
1135 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1136 /* val.i = constant */
1138 var_to_reg_int(s1, src, REG_ITMP1);
1139 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1140 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1141 store_reg_to_var_int(iptr->dst, d);
1144 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1146 var_to_reg_int(s1, src->prev, REG_ITMP1);
1147 var_to_reg_int(s2, src, REG_ITMP2);
1148 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1149 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1150 M_SRA(s1, REG_ITMP3, d);
1151 store_reg_to_var_int(iptr->dst, d);
1154 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1155 /* val.i = constant */
1157 var_to_reg_int(s1, src, REG_ITMP1);
1158 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1159 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1160 store_reg_to_var_int(iptr->dst, d);
1163 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1165 var_to_reg_int(s1, src->prev, REG_ITMP1);
1166 var_to_reg_int(s2, src, REG_ITMP2);
1167 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1168 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1169 M_SRL(s1, REG_ITMP2, d);
1170 store_reg_to_var_int(iptr->dst, d);
1173 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1174 /* val.i = constant */
1176 var_to_reg_int(s1, src, REG_ITMP1);
1177 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1178 if (iptr->val.i & 0x1f)
1179 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1182 store_reg_to_var_int(iptr->dst, d);
1185 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1187 var_to_reg_int(s1, src->prev, REG_ITMP1);
1188 var_to_reg_int(s2, src, REG_ITMP2);
1189 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1191 store_reg_to_var_int(iptr->dst, d);
1194 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1195 /* val.i = constant */
1197 var_to_reg_int(s1, src, REG_ITMP1);
1198 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1199 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1200 M_AND_IMM(s1, iptr->val.i, d);
1203 else if (iptr->val.i == 0xffffff) {
1204 M_RLWINM(s1, 0, 8, 31, d);
1208 ICONST(REG_ITMP2, iptr->val.i);
1209 M_AND(s1, REG_ITMP2, d);
1211 store_reg_to_var_int(iptr->dst, d);
1214 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1216 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1217 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1218 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1219 M_AND(s1, s2, rd->secondregs[d]);
1220 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1221 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1223 store_reg_to_var_int(iptr->dst, d);
1226 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1227 /* val.l = constant */
1229 s3 = iptr->val.l & 0xffffffff;
1230 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1231 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1232 if ((s3 >= 0) && (s3 <= 65535)) {
1233 M_AND_IMM(s1, s3, rd->secondregs[d]);
1236 ICONST(REG_ITMP2, s3);
1237 M_AND(s1, REG_ITMP2, rd->secondregs[d]);
1239 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1240 s3 = iptr->val.l >> 32;
1241 if ((s3 >= 0) && (s3 <= 65535)) {
1242 M_AND_IMM(s1, s3, d);
1245 ICONST(REG_ITMP3, s3);
1246 M_AND(s1, REG_ITMP3, d);
1248 store_reg_to_var_int(iptr->dst, d);
1251 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1252 /* val.i = constant */
1254 var_to_reg_int(s1, src, REG_ITMP1);
1255 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1256 M_MOV(s1, REG_ITMP2);
1258 M_BGE(1 + 2*(iptr->val.i >= 32768));
1259 if (iptr->val.i >= 32768) {
1260 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1261 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1262 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1265 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1267 int b=0, m = iptr->val.i;
1270 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1272 M_ISUB(s1, REG_ITMP2, d);
1273 store_reg_to_var_int(iptr->dst, d);
1276 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1278 var_to_reg_int(s1, src->prev, REG_ITMP1);
1279 var_to_reg_int(s2, src, REG_ITMP2);
1280 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1282 store_reg_to_var_int(iptr->dst, d);
1285 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1286 /* val.i = constant */
1288 var_to_reg_int(s1, src, REG_ITMP1);
1289 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1290 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1291 M_OR_IMM(s1, iptr->val.i, d);
1294 ICONST(REG_ITMP2, iptr->val.i);
1295 M_OR(s1, REG_ITMP2, d);
1297 store_reg_to_var_int(iptr->dst, d);
1300 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1302 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1303 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1304 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1305 M_OR(s1, s2, rd->secondregs[d]);
1306 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1307 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1309 store_reg_to_var_int(iptr->dst, d);
1312 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1313 /* val.l = constant */
1315 s3 = iptr->val.l & 0xffffffff;
1316 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1317 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1318 if ((s3 >= 0) && (s3 <= 65535)) {
1319 M_OR_IMM(s1, s3, rd->secondregs[d]);
1322 ICONST(REG_ITMP2, s3);
1323 M_OR(s1, REG_ITMP2, rd->secondregs[d]);
1325 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1326 s3 = iptr->val.l >> 32;
1327 if ((s3 >= 0) && (s3 <= 65535)) {
1328 M_OR_IMM(s1, s3, d);
1331 ICONST(REG_ITMP3, s3);
1332 M_OR(s1, REG_ITMP3, d);
1334 store_reg_to_var_int(iptr->dst, d);
1337 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1339 var_to_reg_int(s1, src->prev, REG_ITMP1);
1340 var_to_reg_int(s2, src, REG_ITMP2);
1341 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1343 store_reg_to_var_int(iptr->dst, d);
1346 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1347 /* val.i = constant */
1349 var_to_reg_int(s1, src, REG_ITMP1);
1350 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1351 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1352 M_XOR_IMM(s1, iptr->val.i, d);
1355 ICONST(REG_ITMP2, iptr->val.i);
1356 M_XOR(s1, REG_ITMP2, d);
1358 store_reg_to_var_int(iptr->dst, d);
1361 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1363 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1364 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1365 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1366 M_XOR(s1, s2, rd->secondregs[d]);
1367 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1368 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1370 store_reg_to_var_int(iptr->dst, d);
1373 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1374 /* val.l = constant */
1376 s3 = iptr->val.l & 0xffffffff;
1377 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1378 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1379 if ((s3 >= 0) && (s3 <= 65535)) {
1380 M_XOR_IMM(s1, s3, rd->secondregs[d]);
1383 ICONST(REG_ITMP2, s3);
1384 M_XOR(s1, REG_ITMP2, rd->secondregs[d]);
1386 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1387 s3 = iptr->val.l >> 32;
1388 if ((s3 >= 0) && (s3 <= 65535)) {
1389 M_XOR_IMM(s1, s3, d);
1392 ICONST(REG_ITMP3, s3);
1393 M_XOR(s1, REG_ITMP3, d);
1395 store_reg_to_var_int(iptr->dst, d);
1398 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1400 var_to_reg_int0(s1, src->prev, REG_ITMP3, 1, 0);
1401 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
1402 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1405 (d==s1 || d==s2 || d==rd->secondregs[s1] || d==rd->secondregs[s2]);
1406 int dreg = tempreg ? REG_ITMP1 : d;
1408 M_IADD_IMM(REG_ZERO, 1, dreg);
1413 var_to_reg_int0(s1, src->prev, REG_ITMP3, 0, 1);
1414 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1418 M_IADD_IMM(dreg, -1, dreg);
1419 M_IADD_IMM(dreg, -1, dreg);
1420 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1421 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1424 store_reg_to_var_int(iptr->dst, d);
1427 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1428 /* op1 = variable, val.i = constant */
1430 var = &(rd->locals[iptr->op1][TYPE_INT]);
1431 if (var->flags & INMEMORY) {
1433 M_ILD(s1, REG_SP, 4 * var->regoff);
1442 M_ADDIS(s1, m>>16, s1);
1444 M_IADD_IMM(s1, m&0xffff, s1);
1446 if (var->flags & INMEMORY)
1447 M_IST(s1, REG_SP, 4 * var->regoff);
1451 /* floating operations ************************************************/
1453 case ICMD_FNEG: /* ..., 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_DNEG: /* ..., value ==> ..., - value */
1463 var_to_reg_flt(s1, src, REG_FTMP1);
1464 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1466 store_reg_to_var_flt(iptr->dst, d);
1469 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1471 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1472 var_to_reg_flt(s2, src, REG_FTMP2);
1473 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1475 store_reg_to_var_flt(iptr->dst, d);
1478 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1480 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1481 var_to_reg_flt(s2, src, REG_FTMP2);
1482 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1484 store_reg_to_var_flt(iptr->dst, d);
1487 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1489 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1490 var_to_reg_flt(s2, src, REG_FTMP2);
1491 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1493 store_reg_to_var_flt(iptr->dst, d);
1496 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1498 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1499 var_to_reg_flt(s2, src, REG_FTMP2);
1500 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1502 store_reg_to_var_flt(iptr->dst, d);
1505 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1507 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1508 var_to_reg_flt(s2, src, REG_FTMP2);
1509 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1511 store_reg_to_var_flt(iptr->dst, d);
1514 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1516 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1517 var_to_reg_flt(s2, src, REG_FTMP2);
1518 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1520 store_reg_to_var_flt(iptr->dst, d);
1523 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1525 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1526 var_to_reg_flt(s2, src, REG_FTMP2);
1527 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1529 store_reg_to_var_flt(iptr->dst, d);
1532 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1534 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1535 var_to_reg_flt(s2, src, REG_FTMP2);
1536 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1538 store_reg_to_var_flt(iptr->dst, d);
1541 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1543 var_to_reg_flt(s1, src, REG_FTMP1);
1544 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1546 a = dseg_addfloat(cd, 0.0);
1547 M_FLD(REG_FTMP2, REG_PV, a);
1548 M_FCMPU(s1, REG_FTMP2);
1550 a = dseg_adds4(cd, 0);
1551 M_CVTDL_C(s1, REG_FTMP1);
1552 M_LDA (REG_ITMP1, REG_PV, a);
1553 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1554 M_ILD (d, REG_PV, a);
1555 store_reg_to_var_int(iptr->dst, d);
1558 case ICMD_F2D: /* ..., 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_D2F: /* ..., value ==> ..., (double) value */
1568 var_to_reg_flt(s1, src, REG_FTMP1);
1569 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1571 store_reg_to_var_flt(iptr->dst, d);
1574 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1576 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1577 var_to_reg_flt(s2, src, REG_FTMP2);
1578 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1580 M_IADD_IMM(0, -1, d);
1583 M_IADD_IMM(0, 0, d);
1585 M_IADD_IMM(0, 1, d);
1586 store_reg_to_var_int(iptr->dst, d);
1589 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1591 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1592 var_to_reg_flt(s2, src, REG_FTMP2);
1593 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1595 M_IADD_IMM(0, 1, d);
1598 M_IADD_IMM(0, 0, d);
1600 M_IADD_IMM(0, -1, d);
1601 store_reg_to_var_int(iptr->dst, d);
1605 /* memory operations **************************************************/
1607 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1609 var_to_reg_int(s1, src, REG_ITMP1);
1610 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1611 gen_nullptr_check(s1);
1612 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1613 store_reg_to_var_int(iptr->dst, d);
1616 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1618 var_to_reg_int(s1, src->prev, REG_ITMP1);
1619 var_to_reg_int(s2, src, REG_ITMP2);
1620 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1621 if (iptr->op1 == 0) {
1622 gen_nullptr_check(s1);
1625 M_SLL_IMM(s2, 2, REG_ITMP2);
1626 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1627 M_LWZX(d, s1, REG_ITMP2);
1628 store_reg_to_var_int(iptr->dst, d);
1631 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1633 var_to_reg_int(s1, src->prev, REG_ITMP1);
1634 var_to_reg_int(s2, src, REG_ITMP2);
1635 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1636 if (iptr->op1 == 0) {
1637 gen_nullptr_check(s1);
1640 M_SLL_IMM(s2, 3, REG_ITMP2);
1641 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1642 M_ILD(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
1643 M_ILD(rd->secondregs[d], REG_ITMP2, OFFSET(java_longarray, data[0])+4);
1644 store_reg_to_var_int(iptr->dst, d);
1647 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1649 var_to_reg_int(s1, src->prev, REG_ITMP1);
1650 var_to_reg_int(s2, src, REG_ITMP2);
1651 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1652 if (iptr->op1 == 0) {
1653 gen_nullptr_check(s1);
1656 M_SLL_IMM(s2, 2, REG_ITMP2);
1657 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1658 M_LWZX(d, s1, REG_ITMP2);
1659 store_reg_to_var_int(iptr->dst, d);
1662 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1664 var_to_reg_int(s1, src->prev, REG_ITMP1);
1665 var_to_reg_int(s2, src, REG_ITMP2);
1666 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1667 if (iptr->op1 == 0) {
1668 gen_nullptr_check(s1);
1671 M_SLL_IMM(s2, 2, REG_ITMP2);
1672 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1673 M_LFSX(d, s1, REG_ITMP2);
1674 store_reg_to_var_flt(iptr->dst, d);
1677 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1679 var_to_reg_int(s1, src->prev, REG_ITMP1);
1680 var_to_reg_int(s2, src, REG_ITMP2);
1681 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1682 if (iptr->op1 == 0) {
1683 gen_nullptr_check(s1);
1686 M_SLL_IMM(s2, 3, REG_ITMP2);
1687 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1688 M_LFDX(d, s1, REG_ITMP2);
1689 store_reg_to_var_flt(iptr->dst, d);
1692 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1694 var_to_reg_int(s1, src->prev, REG_ITMP1);
1695 var_to_reg_int(s2, src, REG_ITMP2);
1696 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1697 if (iptr->op1 == 0) {
1698 gen_nullptr_check(s1);
1701 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1702 M_LBZX(d, s1, REG_ITMP2);
1704 store_reg_to_var_int(iptr->dst, d);
1707 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1709 var_to_reg_int(s1, src->prev, REG_ITMP1);
1710 var_to_reg_int(s2, src, REG_ITMP2);
1711 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1712 if (iptr->op1 == 0) {
1713 gen_nullptr_check(s1);
1716 M_SLL_IMM(s2, 1, REG_ITMP2);
1717 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1718 M_LHAX(d, s1, REG_ITMP2);
1719 store_reg_to_var_int(iptr->dst, d);
1722 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1724 var_to_reg_int(s1, src->prev, REG_ITMP1);
1725 var_to_reg_int(s2, src, REG_ITMP2);
1726 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1727 if (iptr->op1 == 0) {
1728 gen_nullptr_check(s1);
1731 M_SLL_IMM(s2, 1, REG_ITMP2);
1732 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1733 M_LHZX(d, s1, REG_ITMP2);
1734 store_reg_to_var_int(iptr->dst, d);
1737 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1739 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1740 var_to_reg_int(s2, src->prev, REG_ITMP2);
1741 if (iptr->op1 == 0) {
1742 gen_nullptr_check(s1);
1745 var_to_reg_int0(s3, src, REG_ITMP3, 1, 0);
1746 M_SLL_IMM(s2, 3, REG_ITMP2);
1747 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1748 M_STWX(s3, s1, REG_ITMP2);
1749 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1750 var_to_reg_int0(s3, src, REG_ITMP3, 0, 1);
1751 M_STWX(s3, s1, REG_ITMP2);
1754 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1756 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1757 var_to_reg_int(s2, src->prev, REG_ITMP2);
1758 if (iptr->op1 == 0) {
1759 gen_nullptr_check(s1);
1762 var_to_reg_int(s3, src, REG_ITMP3);
1763 M_SLL_IMM(s2, 2, REG_ITMP2);
1764 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1765 M_STWX(s3, s1, REG_ITMP2);
1768 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1770 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1771 var_to_reg_int(s2, src->prev, REG_ITMP2);
1772 if (iptr->op1 == 0) {
1773 gen_nullptr_check(s1);
1776 var_to_reg_flt(s3, src, REG_FTMP3);
1777 M_SLL_IMM(s2, 2, REG_ITMP2);
1778 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1779 M_STFSX(s3, s1, REG_ITMP2);
1782 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1784 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1785 var_to_reg_int(s2, src->prev, REG_ITMP2);
1786 if (iptr->op1 == 0) {
1787 gen_nullptr_check(s1);
1790 var_to_reg_flt(s3, src, REG_FTMP3);
1791 M_SLL_IMM(s2, 3, REG_ITMP2);
1792 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1793 M_STFDX(s3, s1, REG_ITMP2);
1796 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1798 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1799 var_to_reg_int(s2, src->prev, REG_ITMP2);
1800 if (iptr->op1 == 0) {
1801 gen_nullptr_check(s1);
1804 var_to_reg_int(s3, src, REG_ITMP3);
1805 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1806 M_STBX(s3, s1, REG_ITMP2);
1809 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1811 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1812 var_to_reg_int(s2, src->prev, REG_ITMP2);
1813 if (iptr->op1 == 0) {
1814 gen_nullptr_check(s1);
1817 var_to_reg_int(s3, src, REG_ITMP3);
1818 M_SLL_IMM(s2, 1, REG_ITMP2);
1819 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1820 M_STHX(s3, s1, REG_ITMP2);
1823 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1825 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1826 var_to_reg_int(s2, src->prev, REG_ITMP2);
1827 if (iptr->op1 == 0) {
1828 gen_nullptr_check(s1);
1831 var_to_reg_int(s3, src, REG_ITMP3);
1832 M_SLL_IMM(s2, 1, REG_ITMP2);
1833 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1834 M_STHX(s3, s1, REG_ITMP2);
1838 case ICMD_GETSTATIC: /* ... ==> ..., value */
1839 /* op1 = type, val.a = field address */
1842 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1843 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1845 M_ALD(REG_ITMP1, REG_PV, a);
1846 a = dseg_addaddress(cd, asm_wrapper_patcher);
1847 M_ALD(REG_ITMP2, REG_PV, a);
1853 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1855 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1857 s4 ml = -s1, mh = 0;
1858 while (ml < -32768) { ml += 65536; mh--; }
1859 M_LDA(REG_PV, REG_ITMP1, ml);
1860 M_LDAH(REG_PV, REG_PV, mh);
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);
1897 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1898 /* op1 = type, val.a = field address */
1900 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1901 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1902 M_ALD(REG_ITMP1, REG_PV, a);
1903 a = dseg_addaddress(cd, asm_wrapper_patcher);
1904 M_ALD(REG_ITMP2, REG_PV, a);
1910 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1912 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1914 s4 ml = -s1, mh = 0;
1915 while (ml < -32768) { ml += 65536; mh--; }
1916 M_LDA(REG_PV, REG_ITMP1, ml);
1917 M_LDAH(REG_PV, REG_PV, mh);
1923 fieldinfo *fi = iptr->val.a;
1925 if (!fi->class->initialized) {
1926 codegen_addpatchref(cd, mcodeptr,
1927 /* PATCHER_clinit, fi->class);*/
1930 if (showdisassemble)
1934 a = (ptrint) &(fi->value);
1937 a = dseg_addaddress(cd, a);
1939 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1940 M_ALD(REG_ITMP1, REG_PV, a);
1941 switch (iptr->op1) {
1943 var_to_reg_int(s2, src, REG_ITMP2);
1944 M_IST(s2, REG_ITMP1, 0);
1947 var_to_reg_int(s2, src, REG_ITMP3);
1948 M_IST(s2, REG_ITMP1, 0);
1949 M_IST(rd->secondregs[s2], REG_ITMP1, 4);
1952 var_to_reg_int(s2, src, REG_ITMP2);
1953 M_AST(s2, REG_ITMP1, 0);
1956 var_to_reg_flt(s2, src, REG_FTMP2);
1957 M_FST(s2, REG_ITMP1, 0);
1960 var_to_reg_flt(s2, src, REG_FTMP2);
1961 M_DST(s2, REG_ITMP1, 0);
1967 case ICMD_GETFIELD: /* ... ==> ..., value */
1968 /* op1 = type, val.i = field offset */
1970 a = ((fieldinfo *)(iptr->val.a))->offset;
1971 switch (iptr->op1) {
1973 var_to_reg_int(s1, src, REG_ITMP1);
1974 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1975 gen_nullptr_check(s1);
1977 store_reg_to_var_int(iptr->dst, d);
1980 var_to_reg_int(s1, src, REG_ITMP1);
1981 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1982 gen_nullptr_check(s1);
1984 M_ILD(rd->secondregs[d], s1, a+4);
1985 store_reg_to_var_int(iptr->dst, d);
1988 var_to_reg_int(s1, src, REG_ITMP1);
1989 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1990 gen_nullptr_check(s1);
1992 store_reg_to_var_int(iptr->dst, d);
1995 var_to_reg_int(s1, src, REG_ITMP1);
1996 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1997 gen_nullptr_check(s1);
1999 store_reg_to_var_flt(iptr->dst, d);
2002 var_to_reg_int(s1, src, REG_ITMP1);
2003 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2004 gen_nullptr_check(s1);
2006 store_reg_to_var_flt(iptr->dst, d);
2011 case ICMD_PUTFIELD: /* ..., value ==> ... */
2012 /* op1 = type, val.i = field offset */
2014 a = ((fieldinfo *)(iptr->val.a))->offset;
2015 switch (iptr->op1) {
2017 var_to_reg_int(s1, src->prev, REG_ITMP1);
2018 var_to_reg_int(s2, src, REG_ITMP2);
2019 gen_nullptr_check(s1);
2023 var_to_reg_int(s1, src->prev, REG_ITMP1);
2024 var_to_reg_int(s2, src, REG_ITMP3);
2025 gen_nullptr_check(s1);
2027 M_IST(rd->secondregs[s2], s1, a+4);
2030 var_to_reg_int(s1, src->prev, REG_ITMP1);
2031 var_to_reg_int(s2, src, REG_ITMP2);
2032 gen_nullptr_check(s1);
2036 var_to_reg_int(s1, src->prev, REG_ITMP1);
2037 var_to_reg_flt(s2, src, REG_FTMP2);
2038 gen_nullptr_check(s1);
2042 var_to_reg_int(s1, src->prev, REG_ITMP1);
2043 var_to_reg_flt(s2, src, REG_FTMP2);
2044 gen_nullptr_check(s1);
2051 /* branch operations **************************************************/
2053 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2055 a = dseg_addaddress(cd, asm_handle_exception);
2056 M_ALD(REG_ITMP2, REG_PV, a);
2058 var_to_reg_int(s1, src, REG_ITMP1);
2059 M_INTMOVE(s1, REG_ITMP1_XPTR);
2061 if (m->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
2062 M_BL(0); /* get current PC */
2063 M_MFLR(REG_ITMP2_XPC);
2064 if (m->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
2065 M_RTS; /* jump to CTR */
2070 case ICMD_GOTO: /* ... ==> ... */
2071 /* op1 = target JavaVM pc */
2073 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2077 case ICMD_JSR: /* ... ==> ... */
2078 /* op1 = target JavaVM pc */
2080 if (m->isleafmethod) M_MFLR(REG_ITMP2);
2083 M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
2084 if (m->isleafmethod) M_MTLR(REG_ITMP2);
2086 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2089 case ICMD_RET: /* ... ==> ... */
2090 /* op1 = local variable */
2092 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2093 if (var->flags & INMEMORY) {
2094 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
2098 M_MTCTR(var->regoff);
2103 case ICMD_IFNULL: /* ..., value ==> ... */
2104 /* op1 = target JavaVM pc */
2106 var_to_reg_int(s1, src, REG_ITMP1);
2109 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2112 case ICMD_IFNONNULL: /* ..., value ==> ... */
2113 /* op1 = target JavaVM pc */
2115 var_to_reg_int(s1, src, REG_ITMP1);
2118 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2126 case ICMD_IFEQ: /* ..., value ==> ... */
2127 /* op1 = target JavaVM pc, val.i = constant */
2129 var_to_reg_int(s1, src, REG_ITMP1);
2130 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2131 M_CMPI(s1, iptr->val.i);
2134 ICONST(REG_ITMP2, iptr->val.i);
2135 M_CMP(s1, REG_ITMP2);
2158 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2162 case ICMD_IF_LEQ: /* ..., value ==> ... */
2163 /* 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);
2171 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2172 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2174 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2177 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2178 M_CMP(s2, REG_ITMP3);
2180 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2181 M_CMP(s1, REG_ITMP3)
2184 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2187 case ICMD_IF_LLT: /* ..., value ==> ... */
2188 /* op1 = target JavaVM pc, val.l = constant */
2189 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2190 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2191 /* if (iptr->val.l == 0) { */
2192 /* M_OR(s1, s2, REG_ITMP3); */
2193 /* M_CMPI(REG_ITMP3, 0); */
2196 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2197 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2199 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2201 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2204 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2205 M_CMP(s2, REG_ITMP3);
2207 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2209 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2210 M_CMP(s1, REG_ITMP3)
2213 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2216 case ICMD_IF_LLE: /* ..., value ==> ... */
2217 /* op1 = target JavaVM pc, val.l = constant */
2219 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2220 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2221 /* if (iptr->val.l == 0) { */
2222 /* M_OR(s1, s2, REG_ITMP3); */
2223 /* M_CMPI(REG_ITMP3, 0); */
2226 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2227 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2229 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2231 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2234 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2235 M_CMP(s2, REG_ITMP3);
2237 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2239 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2240 M_CMP(s1, REG_ITMP3)
2243 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2246 case ICMD_IF_LNE: /* ..., value ==> ... */
2247 /* op1 = target JavaVM pc, val.l = constant */
2249 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2250 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2251 if (iptr->val.l == 0) {
2252 M_OR(s1, s2, REG_ITMP3);
2253 M_CMPI(REG_ITMP3, 0);
2255 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2256 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2258 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2261 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2262 M_CMP(s2, REG_ITMP3);
2264 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2265 M_CMP(s1, REG_ITMP3)
2268 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2271 case ICMD_IF_LGT: /* ..., value ==> ... */
2272 /* op1 = target JavaVM pc, val.l = constant */
2274 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2275 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2276 /* if (iptr->val.l == 0) { */
2277 /* M_OR(s1, s2, REG_ITMP3); */
2278 /* M_CMPI(REG_ITMP3, 0); */
2281 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2282 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2284 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2286 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2289 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2290 M_CMP(s2, REG_ITMP3);
2292 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2294 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2295 M_CMP(s1, REG_ITMP3)
2298 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2301 case ICMD_IF_LGE: /* ..., value ==> ... */
2302 /* op1 = target JavaVM pc, val.l = constant */
2303 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2304 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2305 /* if (iptr->val.l == 0) { */
2306 /* M_OR(s1, s2, REG_ITMP3); */
2307 /* M_CMPI(REG_ITMP3, 0); */
2310 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2311 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2313 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2315 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2318 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2319 M_CMP(s2, REG_ITMP3);
2321 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2323 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2324 M_CMP(s1, REG_ITMP3)
2327 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2331 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2332 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2333 case ICMD_IF_ACMPEQ:
2335 var_to_reg_int(s1, src->prev, REG_ITMP1);
2336 var_to_reg_int(s2, src, REG_ITMP2);
2339 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2342 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2343 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2344 case ICMD_IF_ACMPNE:
2346 var_to_reg_int(s1, src->prev, REG_ITMP1);
2347 var_to_reg_int(s2, src, REG_ITMP2);
2350 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2353 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2354 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2356 var_to_reg_int(s1, src->prev, REG_ITMP1);
2357 var_to_reg_int(s2, src, REG_ITMP2);
2360 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2363 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2364 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2366 var_to_reg_int(s1, src->prev, REG_ITMP1);
2367 var_to_reg_int(s2, src, REG_ITMP2);
2370 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2373 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2374 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2376 var_to_reg_int(s1, src->prev, REG_ITMP1);
2377 var_to_reg_int(s2, src, REG_ITMP2);
2380 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2383 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2384 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2386 var_to_reg_int(s1, src->prev, REG_ITMP1);
2387 var_to_reg_int(s2, src, REG_ITMP2);
2390 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2393 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2396 var_to_reg_int(s1, src, REG_RESULT);
2397 M_TINTMOVE(src->type, s1, REG_RESULT);
2398 goto nowperformreturn;
2400 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2402 var_to_reg_flt(s1, src, REG_FRESULT);
2403 M_FLTMOVE(s1, REG_FRESULT);
2404 goto nowperformreturn;
2406 case ICMD_RETURN: /* ... ==> ... */
2414 p = parentargs_base;
2415 /* call trace function */
2419 M_LDA(REG_SP, REG_SP, -10 * 8);
2420 M_DST(REG_FRESULT, REG_SP, 48+0);
2421 M_IST(REG_RESULT, REG_SP, 48+8);
2422 M_AST(REG_ITMP3, REG_SP, 48+12);
2423 M_IST(REG_RESULT2, REG_SP, 48+16);
2424 a = dseg_addaddress(cd, m);
2426 /* keep this order */
2427 switch (iptr->opc) {
2430 M_MOV(REG_RESULT, rd->argintregs[2]);
2431 M_CLR(rd->argintregs[1]);
2435 M_MOV(REG_RESULT2, rd->argintregs[2]);
2436 M_MOV(REG_RESULT, rd->argintregs[1]);
2439 M_ALD(rd->argintregs[0], REG_PV, a);
2441 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2442 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2443 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2444 M_ALD(REG_ITMP2, REG_PV, a);
2447 M_DLD(REG_FRESULT, REG_SP, 48+0);
2448 M_ILD(REG_RESULT, REG_SP, 48+8);
2449 M_ALD(REG_ITMP3, REG_SP, 48+12);
2450 M_ILD(REG_RESULT2, REG_SP, 48+16);
2451 M_LDA(REG_SP, REG_SP, 10 * 8);
2455 #if defined(USE_THREADS)
2456 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2457 /* we need to save the proper return value */
2458 switch (iptr->opc) {
2461 M_IST(REG_RESULT , REG_SP, rd->maxmemuse * 4 + 4);
2463 M_IST(REG_RESULT2, REG_SP, rd->maxmemuse * 4 + 8);
2466 M_FST(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2469 M_DST(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2473 a = dseg_addaddress(cd, (void *) (builtin_monitorexit));
2474 M_ALD(REG_ITMP3, REG_PV, a);
2476 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
2479 /* and now restore the proper return value */
2480 switch (iptr->opc) {
2483 M_ILD(REG_RESULT , REG_SP, rd->maxmemuse * 4 + 4);
2485 M_ILD(REG_RESULT2, REG_SP, rd->maxmemuse * 4 + 8);
2488 M_FLD(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2491 M_DLD(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2497 /* restore return address */
2499 if (!m->isleafmethod) {
2500 M_ALD(REG_ITMP3, REG_SP, 4 * p + 8);
2504 /* restore saved registers */
2506 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2507 p--; M_ILD(rd->savintregs[i], REG_SP, 4 * p);
2509 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2510 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, 4 * p);
2513 /* deallocate stack */
2515 if (parentargs_base) {
2516 M_LDA(REG_SP, REG_SP, parentargs_base*4);
2527 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2532 tptr = (void **) iptr->target;
2534 s4ptr = iptr->val.a;
2535 l = s4ptr[1]; /* low */
2536 i = s4ptr[2]; /* high */
2538 var_to_reg_int(s1, src, REG_ITMP1);
2540 M_INTMOVE(s1, REG_ITMP1);
2541 } else if (l <= 32768) {
2542 M_LDA(REG_ITMP1, s1, -l);
2544 ICONST(REG_ITMP2, l);
2545 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2551 M_CMPUI(REG_ITMP1, i - 1);
2554 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2555 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2557 /* build jump table top down and use address of lowest entry */
2559 /* s4ptr += 3 + i; */
2563 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2564 dseg_addtarget(cd, (basicblock *) tptr[0]);
2569 /* length of dataseg after last dseg_addtarget is used by load */
2571 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2572 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2573 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2580 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2582 s4 i, l, val, *s4ptr;
2585 tptr = (void **) iptr->target;
2587 s4ptr = iptr->val.a;
2588 l = s4ptr[0]; /* default */
2589 i = s4ptr[1]; /* count */
2591 MCODECHECK((i<<2)+8);
2592 var_to_reg_int(s1, src, REG_ITMP1);
2598 if ((val >= -32768) && (val <= 32767)) {
2602 a = dseg_adds4(cd, val);
2603 M_ILD(REG_ITMP2, REG_PV, a);
2604 M_CMP(s1, REG_ITMP2);
2607 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2608 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2612 /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2614 tptr = (void **) iptr->target;
2615 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2622 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2623 /* op1 = return type, val.a = function pointer*/
2627 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2628 /* op1 = return type, val.a = function pointer*/
2632 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2633 /* op1 = return type, val.a = function pointer*/
2637 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2638 /* op1 = arg count, val.a = method pointer */
2640 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2641 /* op1 = arg count, val.a = method pointer */
2643 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2644 /* op1 = arg count, val.a = method pointer */
2646 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2647 /* op1 = arg count, val.a = method pointer */
2655 MCODECHECK((s3 << 1) + 64);
2658 /* copy arguments to registers or stack location */
2660 stackptr srcsave = src;
2664 for (; --s3 >= 0; src = src->prev) {
2665 argsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
2666 if (IS_FLT_DBL_TYPE(src->type))
2670 for (s3 = s3save, src = srcsave; --s3 >= 0; src = src->prev) {
2671 argsize -= IS_2_WORD_TYPE(src->type) ? 2 : 1;
2672 if (IS_FLT_DBL_TYPE(src->type))
2674 if (src->varkind == ARGVAR)
2676 if (IS_INT_LNG_TYPE(src->type)) {
2677 if (argsize < INT_ARG_CNT) {
2678 s1 = rd->argintregs[argsize];
2679 var_to_reg_int(d, src, s1);
2680 if (argsize < INT_ARG_CNT-1) {
2681 M_TINTMOVE(src->type, d, s1);
2685 if (IS_2_WORD_TYPE(src->type))
2686 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2690 var_to_reg_int(d, src, REG_ITMP1);
2691 M_IST(d, REG_SP, 4 * (argsize + 6));
2692 if (IS_2_WORD_TYPE(src->type))
2693 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2697 if (fltcnt < FLT_ARG_CNT) {
2698 s1 = rd->argfltregs[fltcnt];
2699 var_to_reg_flt(d, src, s1);
2703 var_to_reg_flt(d, src, REG_FTMP1);
2704 if (IS_2_WORD_TYPE(src->type))
2705 M_DST(d, REG_SP, 4 * (argsize + 6));
2707 M_FST(d, REG_SP, 4 * (argsize + 6));
2714 switch (iptr->opc) {
2718 a = dseg_addaddress(cd, (void *) lm);
2720 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2722 goto makeactualcall;
2724 case ICMD_INVOKESTATIC:
2725 case ICMD_INVOKESPECIAL:
2726 a = dseg_addaddress(cd, lm->stubroutine);
2728 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
2731 goto makeactualcall;
2733 case ICMD_INVOKEVIRTUAL:
2735 gen_nullptr_check(rd->argintregs[0]);
2736 M_ALD(REG_METHODPTR, rd->argintregs[0],
2737 OFFSET(java_objectheader, vftbl));
2738 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) +
2739 sizeof(methodptr) * lm->vftblindex);
2742 goto makeactualcall;
2744 case ICMD_INVOKEINTERFACE:
2747 gen_nullptr_check(rd->argintregs[0]);
2748 M_ALD(REG_METHODPTR, rd->argintregs[0],
2749 OFFSET(java_objectheader, vftbl));
2750 M_ALD(REG_METHODPTR, REG_METHODPTR,
2751 OFFSET(vftbl_t, interfacetable[0]) -
2752 sizeof(methodptr*) * ci->index);
2753 M_ALD(REG_PV, REG_METHODPTR,
2754 sizeof(methodptr) * (lm - ci->methods));
2757 goto makeactualcall;
2766 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2768 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2770 s4 ml = -s1, mh = 0;
2771 while (ml < -32768) { ml += 65536; mh--; }
2772 M_LDA(REG_PV, REG_ITMP1, ml);
2773 M_LDAH(REG_PV, REG_PV, mh);
2776 /* d contains return type */
2778 if (d != TYPE_VOID) {
2779 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2780 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2781 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2782 store_reg_to_var_int(iptr->dst, s1);
2785 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2786 M_FLTMOVE(REG_FRESULT, s1);
2787 store_reg_to_var_flt(iptr->dst, s1);
2794 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2796 /* op1: 0 == array, 1 == class */
2797 /* val.a: (classinfo*) superclass */
2799 /* superclass is an interface:
2801 * return (sub != NULL) &&
2802 * (sub->vftbl->interfacetablelength > super->index) &&
2803 * (sub->vftbl->interfacetable[-super->index] != NULL);
2805 * superclass is a class:
2807 * return ((sub != NULL) && (0
2808 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2809 * super->vftbl->diffvall));
2813 classinfo *super = (classinfo*) iptr->val.a;
2815 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2816 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2818 var_to_reg_int(s1, src, REG_ITMP1);
2819 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2821 M_MOV(s1, REG_ITMP1);
2825 if (iptr->op1) { /* class/interface */
2827 if (super->flags & ACC_INTERFACE) { /* interface */
2829 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2830 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2831 M_LDATST(REG_ITMP2, REG_ITMP2, - super->index);
2833 M_ALD(REG_ITMP1, REG_ITMP1,
2834 OFFSET(vftbl_t, interfacetable[0]) -
2835 super->index * sizeof(methodptr*));
2839 M_IADD_IMM(REG_ZERO, 1, d);
2843 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2844 a = dseg_addaddress(cd, (void*) super->vftbl);
2845 M_ALD(REG_ITMP2, REG_PV, a);
2846 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2847 codegen_threadcritstart(cd, (u1*) mcodeptr - cd->mcodebase);
2849 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2850 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2851 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2852 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2853 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2855 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2856 M_CMPU(REG_ITMP1, REG_ITMP2);
2859 M_IADD_IMM(REG_ZERO, 1, d);
2863 store_reg_to_var_int(iptr->dst, d);
2866 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2868 /* op1: 0 == array, 1 == class */
2869 /* val.a: (classinfo*) superclass */
2871 /* superclass is an interface:
2873 * OK if ((sub == NULL) ||
2874 * (sub->vftbl->interfacetablelength > super->index) &&
2875 * (sub->vftbl->interfacetable[-super->index] != NULL));
2877 * superclass is a class:
2879 * OK if ((sub == NULL) || (0
2880 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2881 * super->vftbl->diffvall));
2885 classinfo *super = (classinfo*) iptr->val.a;
2887 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2888 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2890 var_to_reg_int(s1, src, REG_ITMP1);
2891 if (iptr->op1) { /* class/interface */
2893 if (super->flags & ACC_INTERFACE) { /* interface */
2895 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2896 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2897 M_LDATST(REG_ITMP3, REG_ITMP3, - super->index);
2899 codegen_addxcastrefs(cd, mcodeptr);
2900 M_ALD(REG_ITMP3, REG_ITMP2,
2901 OFFSET(vftbl_t, interfacetable[0]) -
2902 super->index * sizeof(methodptr*));
2905 codegen_addxcastrefs(cd, mcodeptr);
2908 M_BEQ(8 + (s1 == REG_ITMP1));
2909 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2910 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2911 codegen_threadcritstart(cd, (u1*) mcodeptr - cd->mcodebase);
2913 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2914 a = dseg_addaddress(cd, (void*) super->vftbl);
2915 M_ALD(REG_ITMP2, REG_PV, a);
2916 if (s1 != REG_ITMP1) {
2917 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2918 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2919 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2920 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2922 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2925 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2926 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2927 M_ALD(REG_ITMP2, REG_PV, a);
2928 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2929 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2930 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2933 M_CMPU(REG_ITMP3, REG_ITMP2);
2935 codegen_addxcastrefs(cd, mcodeptr);
2939 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2941 store_reg_to_var_int(iptr->dst, d);
2944 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
2946 var_to_reg_int(s1, src, REG_ITMP1);
2949 codegen_addxcheckarefs(cd, mcodeptr);
2952 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
2954 M_CMPI(REG_RESULT, 0);
2956 codegen_addxexceptionrefs(cd, mcodeptr);
2959 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2960 /* op1 = dimension, val.a = array descriptor */
2962 /* check for negative sizes and copy sizes to stack if necessary */
2964 MCODECHECK((iptr->op1 << 1) + 64);
2966 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
2967 var_to_reg_int(s2, src, REG_ITMP1);
2970 codegen_addxcheckarefs(cd, mcodeptr);
2972 /* copy SAVEDVAR sizes to stack */
2974 if (src->varkind != ARGVAR) {
2975 M_IST(s2, REG_SP, (s1 + INT_ARG_CNT + 6) * 4);
2979 /* a0 = dimension count */
2981 ICONST(rd->argintregs[0], iptr->op1);
2983 /* a1 = arraydescriptor */
2985 a = dseg_addaddress(cd, iptr->val.a);
2986 M_ALD(rd->argintregs[1], REG_PV, a);
2988 /* a2 = pointer to dimensions = stack pointer */
2990 M_LDA(rd->argintregs[2], REG_SP, (INT_ARG_CNT + 6) * 4);
2992 a = dseg_addaddress(cd, BUILTIN_multianewarray);
2993 M_ALD(REG_PV, REG_PV, a);
2996 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2999 M_LDA (REG_PV, REG_ITMP1, -s1);
3001 s4 ml = -s1, mh = 0;
3002 while (ml < -32768) {ml += 65536; mh--;}
3003 M_LDA(REG_PV, REG_ITMP1, ml);
3004 M_LDAH(REG_PV, REG_PV, mh);
3006 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3007 M_INTMOVE(REG_RESULT, s1);
3008 store_reg_to_var_int(iptr->dst, s1);
3013 throw_cacao_exception_exit(string_java_lang_InternalError,
3014 "Unknown ICMD %d", iptr->opc);
3017 } /* for instruction */
3019 /* copy values to interface registers */
3021 src = bptr->outstack;
3022 len = bptr->outdepth;
3023 MCODECHECK(64 + len);
3029 if ((src->varkind != STACKVAR)) {
3031 if (IS_FLT_DBL_TYPE(s2)) {
3032 var_to_reg_flt(s1, src, REG_FTMP1);
3033 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3034 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3037 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3041 var_to_reg_int(s1, src, REG_ITMP1);
3042 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3043 M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3046 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3047 if (IS_2_WORD_TYPE(s2))
3048 M_IST(rd->secondregs[s1], REG_SP, rd->interfaces[len][s2].regoff * 4 + 4);
3054 } /* if (bptr -> flags >= BBREACHED) */
3055 } /* for basic block */
3057 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3060 /* generate bound check stubs */
3062 s4 *xcodeptr = NULL;
3065 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3066 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3068 (u1 *) mcodeptr - cd->mcodebase);
3072 /* move index register into REG_ITMP1 */
3073 M_MOV(bref->reg, REG_ITMP1);
3074 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3076 if (xcodeptr != NULL) {
3077 M_BR(xcodeptr - mcodeptr - 1);
3080 xcodeptr = mcodeptr;
3082 M_STWU(REG_SP, REG_SP, -(24 + 2 * 4));
3083 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3085 M_MOV(REG_ITMP1, rd->argintregs[0]);
3087 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3088 M_ALD(REG_ITMP2, REG_PV, a);
3091 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3093 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3094 M_IADD_IMM(REG_SP, 24 + 2 * 4, REG_SP);
3096 a = dseg_addaddress(cd, asm_handle_exception);
3097 M_ALD(REG_ITMP3, REG_PV, a);
3104 /* generate negative array size check stubs */
3108 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3109 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3110 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3112 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3116 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3118 (u1 *) mcodeptr - cd->mcodebase);
3122 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3124 if (xcodeptr != NULL) {
3125 M_BR(xcodeptr - mcodeptr - 1);
3128 xcodeptr = mcodeptr;
3130 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3131 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3133 a = dseg_addaddress(cd, new_negativearraysizeexception);
3134 M_ALD(REG_ITMP2, REG_PV, a);
3137 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3139 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3140 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3142 a = dseg_addaddress(cd, asm_handle_exception);
3143 M_ALD(REG_ITMP3, REG_PV, a);
3150 /* generate cast check stubs */
3154 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3155 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3156 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3158 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3162 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3164 (u1 *) mcodeptr - cd->mcodebase);
3168 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3170 if (xcodeptr != NULL) {
3171 M_BR(xcodeptr - mcodeptr - 1);
3174 xcodeptr = mcodeptr;
3176 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3177 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3179 a = dseg_addaddress(cd, new_classcastexception);
3180 M_ALD(REG_ITMP2, REG_PV, a);
3183 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3185 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3186 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3188 a = dseg_addaddress(cd, asm_handle_exception);
3189 M_ALD(REG_ITMP3, REG_PV, a);
3196 /* generate exception check stubs */
3200 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3201 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3202 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3204 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3208 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3210 (u1 *) mcodeptr - cd->mcodebase);
3214 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3216 if (xcodeptr != NULL) {
3217 M_BR(xcodeptr - mcodeptr - 1);
3220 xcodeptr = mcodeptr;
3222 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3223 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3225 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3226 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3227 M_ALD(REG_ITMP2, REG_PV, a);
3231 /* get the exceptionptr from the ptrprt and clear it */
3232 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3234 M_AST(REG_ITMP3, REG_RESULT, 0);
3236 a = dseg_addaddress(cd, &_exceptionptr);
3237 M_ALD(REG_ITMP2, REG_PV, a);
3239 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);
3241 M_AST(REG_ITMP3, REG_ITMP2, 0);
3244 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3245 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3247 a = dseg_addaddress(cd, asm_handle_exception);
3248 M_ALD(REG_ITMP3, REG_PV, a);
3254 /* generate null pointer check stubs */
3258 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3259 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3260 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3262 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3266 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3268 (u1 *) mcodeptr - cd->mcodebase);
3272 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3274 if (xcodeptr != NULL) {
3275 M_BR(xcodeptr - mcodeptr - 1);
3278 xcodeptr = mcodeptr;
3280 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3281 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3283 a = dseg_addaddress(cd, new_nullpointerexception);
3284 M_ALD(REG_ITMP2, REG_PV, a);
3287 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3289 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3290 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3292 a = dseg_addaddress(cd, asm_handle_exception);
3293 M_ALD(REG_ITMP3, REG_PV, a);
3299 /* generate patcher stub call code */
3306 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3307 /* check code segment size */
3309 MCODECHECK(13 + 4 + 1);
3311 /* Get machine code which is patched back in later. The call is */
3312 /* 1 instruction word long. */
3314 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3317 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3318 /* create a virtual java_objectheader */
3320 /* align data structure to 8-byte */
3324 *((ptrint *) (mcodeptr + 0)) = 0; /* vftbl */
3325 *((ptrint *) (mcodeptr + 1)) = (ptrint) get_dummyLR(); /* monitorPtr */
3327 mcodeptr += 2 * 1; /* mcodeptr is a `u4*' pointer */
3330 /* patch in the call to call the following code (done at compile */
3333 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3334 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3336 M_BL(tmpmcodeptr - (xcodeptr + 1));
3338 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3341 /* create stack frame */
3343 M_IADD_IMM(REG_SP, -5 * 4, REG_SP);
3345 /* move return address onto stack */
3347 M_AST(REG_ITMP3, REG_SP, 4 * 4);
3349 /* move pointer to java_objectheader onto stack */
3351 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3354 M_IADD_IMM(REG_ITMP3, -(3 * 4 + 2 * 4), REG_ITMP3);
3355 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3357 M_AST(REG_ZERO, REG_SP, 3 * 4);
3360 /* move machine code onto stack */
3362 a = dseg_adds4(cd, mcode);
3363 M_ILD(REG_ITMP3, REG_PV, a);
3364 M_IST(REG_ITMP3, REG_SP, 2 * 4);
3366 /* move class/method/field reference onto stack */
3368 a = dseg_addaddress(cd, pref->ref);
3369 M_ALD(REG_ITMP3, REG_PV, a);
3370 M_AST(REG_ITMP3, REG_SP, 1 * 4);
3372 /* move patcher function pointer onto stack */
3374 a = dseg_addaddress(cd, pref->patcher);
3375 M_ALD(REG_ITMP3, REG_PV, a);
3376 M_AST(REG_ITMP3, REG_SP, 0 * 4);
3378 a = dseg_addaddress(cd, asm_wrapper_patcher);
3379 M_ALD(REG_ITMP3, REG_PV, a);
3388 codegen_finish(m, cd, (ptrint) ((u1 *) mcodeptr - cd->mcodebase));
3390 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3394 /* function createcompilerstub *************************************************
3396 creates a stub routine which calls the compiler
3398 *******************************************************************************/
3400 #define COMPSTUBSIZE 6
3402 u1 *createcompilerstub(methodinfo *m)
3404 s4 *s = CNEW (s4, COMPSTUBSIZE); /* memory to hold the stub */
3405 s4 *mcodeptr = s; /* code generation pointer */
3407 M_LDA(REG_ITMP1, REG_PV, 4*4);
3408 M_ALD(REG_PV, REG_PV, 5*4);
3412 s[4] = (s4) m; /* literals to be adressed */
3413 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3415 asm_cacheflush((void*) s, (u1*) mcodeptr - (u1*) s);
3417 #if defined(STATISTICS)
3419 count_cstub_len += COMPSTUBSIZE * 4;
3426 /* function removecompilerstub *************************************************
3428 deletes a compilerstub from memory (simply by freeing it)
3430 *******************************************************************************/
3432 void removecompilerstub(u1 *stub)
3434 CFREE(stub, COMPSTUBSIZE * 4);
3438 /* function: createnativestub **************************************************
3440 creates a stub routine which calls a native method
3442 *******************************************************************************/
3444 #define NATIVESTUB_SIZE 200
3445 #define NATIVESTUB_OFFSET 9
3448 u1 *createnativestub(functionptr f, methodinfo *m)
3450 s4 *s; /* memory to hold the stub */
3453 s4 *mcodeptr; /* code generation pointer */
3454 s4 stackframesize = 0; /* size of stackframe if needed */
3457 t_inlining_globals *id;
3461 /* mark start of dump memory area */
3463 dumpsize = dump_size();
3465 /* setup registers before using it */
3467 rd = DNEW(registerdata);
3468 id = DNEW(t_inlining_globals);
3470 inlining_setup(m, id);
3471 reg_setup(m, rd, id);
3473 method_descriptor2types(m); /* set paramcount and paramtypes */
3475 stubsize = NATIVESTUB_SIZE; /* calculate nativestub size */
3477 s = CNEW(s4, stubsize);
3478 cs = s + NATIVESTUB_OFFSET;
3481 *(cs-1) = (u4) f; /* address of native method */
3482 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3483 *(cs-2) = (u4) builtin_get_exceptionptrptr;
3485 *(cs-2) = (u4) (&_exceptionptr); /* address of exceptionptr */
3487 *(cs-3) = (u4) asm_handle_nat_exception; /* addr of asm exception handler */
3488 *(cs-4) = (u4) (&env); /* addr of jni_environement */
3489 *(cs-5) = (u4) builtin_trace_args;
3491 *(cs-7) = (u4) builtin_displaymethodstop;
3492 *(cs-8) = (u4) m->class;
3493 *(cs-9) = (u4) asm_wrapper_patcher;
3496 M_AST(REG_ITMP1, REG_SP, 8); /* store return address */
3497 /* Build up new Stackframe for native call */
3498 stackframesize = 24; /* 24 Bytes Linkage Area */
3499 stackframesize += (m->flags & ACC_STATIC) ? 8 : 4; /*1 or 2 additional int parameters */
3500 for (i = 0; i < m->paramcount; i++) {
3501 stackframesize += IS_2_WORD_TYPE(m->paramtypes[i]) ? 8 : 4;
3504 if (stackframesize < (24+32)) { /* 24 Byte Linkage Area + 32 Bytes minimum Argument area */
3505 stackframesize = 24+32;
3507 stackframesize = stackframesize + 8; /* Reserve Space to store Result registers */
3508 stackframesize = (stackframesize + 3) & ~3; /* Keep Stack 16 Byte aligned */
3509 M_STWU(REG_SP, REG_SP, -stackframesize); /* build up stackframe */
3511 /* if function is static, check for initialized */
3513 if (m->flags & ACC_STATIC) {
3514 /* if class isn't yet initialized, do it */
3515 if (!m->class->initialized) {
3516 /* call helper function which patches this code */
3517 M_ALD(REG_ITMP1, REG_PV, -8 * 4); /* class */
3518 M_ALD(REG_PV, REG_PV, -9 * 4); /* asm_wrapper_patcher */
3521 disp = -(s4) (mcodeptr - cs) * 4;
3523 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3533 /* M_MFLR(REG_ITMP3); */
3534 /* XXX must be a multiple of 16 */
3535 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
3537 /* M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3541 /* save all arguments into the reserved stack space */
3542 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3543 t = m->paramtypes[p];
3545 if (IS_INT_LNG_TYPE(t)) {
3546 /* overlapping u8's are on the stack */
3547 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
3548 s1 = rd->argintregs[p + longargs + dblargs];
3550 if (!IS_2_WORD_TYPE(t)) {
3551 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3552 M_IST(s1, REG_SP, 24 + p * 8 + 4);
3555 M_IST(s1, REG_SP, 24 + p * 8);
3556 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3561 /* we do not have a data segment here */
3562 /* a = dseg_adds4(cd, 0xdeadbeef);
3563 M_ILD(REG_ITMP1, REG_PV, a); */
3564 M_LDA(REG_ITMP1, REG_ZERO, -1);
3565 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3566 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
3570 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3571 s1 = rd->argfltregs[fltargs + dblargs];
3573 if (!IS_2_WORD_TYPE(t)) {
3574 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3575 M_FST(s1, REG_SP, 24 + p * 8 + 4);
3579 M_DST(s1, REG_SP, 24 + p * 8);
3584 /* this should not happen */
3589 /* TODO: save remaining integer and flaot argument registers */
3591 /* load first 4 arguments into integer argument registers */
3592 for (p = 0; p < 8; p++) {
3593 d = rd->argintregs[p];
3594 M_ILD(d, REG_SP, 24 + p * 4);
3597 M_ALD(REG_ITMP1, REG_PV, -6 * 4);
3598 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
3599 M_ALD(REG_ITMP2, REG_PV, -5 * 4);
3607 /* restore arguments into the reserved stack space */
3608 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3609 t = m->paramtypes[p];
3611 if (IS_INT_LNG_TYPE(t)) {
3612 if ((p + longargs + dblargs) < INT_ARG_CNT) {
3613 s1 = rd->argintregs[p + longargs + dblargs];
3615 if (!IS_2_WORD_TYPE(t)) {
3616 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
3619 M_ILD(s1, REG_SP, 24 + p * 8);
3620 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3626 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3627 s1 = rd->argfltregs[fltargs + dblargs];
3629 if (!IS_2_WORD_TYPE(t)) {
3630 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
3634 M_DLD(s1, REG_SP, 24 + p * 8);
3641 /* M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3643 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
3644 /* M_MTLR(REG_ITMP3); */
3647 /* save argument registers on stack -- if we have to */
3648 /* and copy spilled argument regs from old stack to the new one */
3657 shift = (m->flags & ACC_STATIC) ? 2 : 1;
3658 for (i = 0; i < m->paramcount; i++) {
3659 paramsize = IS_2_WORD_TYPE(m->paramtypes[i]) ? 2 : 1;
3660 if (IS_FLT_DBL_TYPE(m->paramtypes[i])) {
3662 if (farg >= FLT_ARG_CNT) { /* spilled float arg -> copy from old stack */
3663 if (paramsize == 1) { /* float arg */
3664 M_FLD(REG_FTMP1, REG_SP, stackframesize + 24 + 4 * stack_off);
3665 M_FST(REG_FTMP1, REG_SP, 24 + 4*(shift + stack_off));
3666 } else { /* double arg */
3667 M_DLD(REG_FTMP1, REG_SP, stackframesize + 24 + 4 * stack_off);
3668 M_DST(REG_FTMP1, REG_SP, 24 + 4*(shift + stack_off));
3671 } else { /* int arg */
3672 iarg = stack_off; /* int register are not consecutive like the float*/
3673 if (iarg + paramsize -1 < INT_ARG_CNT) {
3674 if ( iarg + paramsize -1 == INT_ARG_CNT - shift ) {
3675 /* int arg reg(s) spilled through shift to stack */
3676 M_IST( rd->argintregs[iarg], REG_SP, 24 + 4 * (shift + stack_off));
3677 if (paramsize == 2) /* spill secondreg, too */
3678 M_IST( rd->argintregs[iarg+1], REG_SP, 24 + 4 * (shift + stack_off) + 4);
3680 } else { /* already spilled int arg -> copy from old stack */
3681 M_ILD(REG_ITMP1, REG_SP, stackframesize + 24 + 4 * stack_off);
3682 M_IST(REG_ITMP1, REG_SP, 24 + 4 * (shift + stack_off));
3683 if (paramsize == 2) { /* long arg -> copy second half, too */
3684 M_ILD(REG_ITMP1, REG_SP, stackframesize + 24 + 4 * stack_off + 4);
3685 M_IST(REG_ITMP1, REG_SP, 24 + 4*(shift + stack_off) + 4);
3689 stack_off += paramsize;
3692 /* now shift integer argument registers */
3693 for (i = m->paramcount - 1; i >=0; i--) {
3694 paramsize = IS_2_WORD_TYPE(m->paramtypes[i]) ? 2 : 1;
3695 stack_off -= paramsize;
3696 if (IS_INT_LNG_TYPE(m->paramtypes[i])) {
3698 if ( iarg + paramsize -1 < INT_ARG_CNT - shift ) {
3699 /* shift integer arg */
3701 M_MOV(rd->argintregs[iarg+1], rd->argintregs[iarg + shift + 1]);
3702 M_MOV(rd->argintregs[iarg], rd->argintregs[iarg + shift]);
3703 } /* else are already spilled to memory */
3708 if (m->flags & ACC_STATIC)
3709 /* put class into second argument register */
3710 M_ALD(rd->argintregs[1], REG_PV, -8 * 4);
3712 /* put env into first argument register */
3713 M_ALD(rd->argintregs[0], REG_PV, -4 * 4);
3715 M_ALD(REG_PV, REG_PV, -1 * 4); /* load adress of native method */
3718 disp = -(s4) (mcodeptr - cs) * 4;
3720 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3722 /* 20 instructions */
3725 M_LDA(REG_SP, REG_SP, -10 * 8);
3726 M_DST(REG_FRESULT, REG_SP, 48+0);
3727 M_IST(REG_RESULT, REG_SP, 48+8);
3728 M_AST(REG_ITMP3, REG_SP, 48+12);
3729 M_IST(REG_RESULT2, REG_SP, 48+16);
3731 /* keep this order */
3732 switch (m->returntype) {
3735 M_MOV(REG_RESULT, rd->argintregs[2]);
3736 M_CLR(rd->argintregs[1]);
3740 M_MOV(REG_RESULT2, rd->argintregs[2]);
3741 M_MOV(REG_RESULT, rd->argintregs[1]);
3744 M_ALD(rd->argintregs[0], REG_PV, -6 * 4);
3746 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
3747 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
3748 M_ALD(REG_ITMP2, REG_PV, -7 * 4);/* builtin_displaymethodstop */
3751 M_DLD(REG_FRESULT, REG_SP, 48+0);
3752 M_ILD(REG_RESULT, REG_SP, 48+8);
3753 M_ALD(REG_ITMP3, REG_SP, 48+12);
3754 M_ILD(REG_RESULT2, REG_SP, 48+16);
3755 M_LDA(REG_SP, REG_SP, 10 * 8);
3759 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3760 if (IS_FLT_DBL_TYPE(m->returntype))
3761 if (IS_2_WORD_TYPE(m->returntype))
3762 M_DST(REG_FRESULT, REG_SP, stackframesize-8 /*56*/);
3764 M_FST(REG_FRESULT, REG_SP, stackframesize-8 /*56*/);
3766 M_IST(REG_RESULT, REG_SP, stackframesize-8 /*56*/);
3767 if (IS_2_WORD_TYPE(m->returntype))
3768 M_IST(REG_RESULT2, REG_SP, stackframesize-4 /* 60*/);
3771 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* builtin_get_exceptionptrptr */
3774 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3776 M_LDA(REG_PV, REG_ITMP1, disp);
3777 M_MOV(REG_RESULT, REG_ITMP2);
3779 if (IS_FLT_DBL_TYPE(m->returntype))
3780 if (IS_2_WORD_TYPE(m->returntype))
3781 M_DLD(REG_FRESULT, REG_SP, stackframesize-8 /*56*/);
3783 M_FLD(REG_FRESULT, REG_SP, stackframesize-8 /*56*/);
3785 M_ILD(REG_RESULT, REG_SP, stackframesize-8 /*56*/);
3786 if (IS_2_WORD_TYPE(m->returntype))
3787 M_ILD(REG_RESULT2, REG_SP, stackframesize-4 /*60*/);
3790 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* get address of exceptionptr */
3792 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);/* load exception into reg. itmp1 */
3793 M_TST(REG_ITMP1_XPTR);
3794 M_BNE(4); /* if no exception then return */
3796 M_ALD(REG_ITMP1, REG_SP, stackframesize + 8); /* load return address */
3798 M_LDA(REG_SP, REG_SP, stackframesize); /* remove stackframe */
3803 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
3805 M_ALD(REG_ITMP2, REG_SP, stackframesize + 8); /* load return address */
3808 M_LDA(REG_SP, REG_SP, stackframesize); /* remove stackframe */
3810 M_IADD_IMM(REG_ITMP2, -4, REG_ITMP2_XPC); /* fault address */
3812 M_ALD(REG_ITMP3, REG_PV, -3 * 4); /* load asm exception handler address */
3816 /* Check if the stub size is big enough to hold the whole stub generated. */
3817 /* If not, this can lead into unpredictable crashes, because of heap */
3819 if ((s4) (mcodeptr - s) > stubsize) {
3820 throw_cacao_exception_exit(string_java_lang_InternalError,
3821 "Native stub size %d is to small for current stub size %d",
3822 stubsize, (s4) (mcodeptr - s));
3825 asm_cacheflush((void *) s, (u1*) mcodeptr - (u1*) s);
3827 #if defined(STATISTICS)
3829 count_nstub_len += NATIVESTUB_SIZE * 4;
3832 /* release dump area */
3834 dump_release(dumpsize);
3836 return (u1*) (s + NATIVESTUB_OFFSET);
3840 /* function: removenativestub **************************************************
3842 removes a previously created native-stub from memory
3844 *******************************************************************************/
3846 void removenativestub(u1 *stub)
3848 CFREE((s4 *) stub - NATIVESTUB_OFFSET, NATIVESTUB_SIZE * 4);
3853 * These are local overrides for various environment variables in Emacs.
3854 * Please do not remove this and leave it at the end of the file, where
3855 * Emacs will automagically detect them.
3856 * ---------------------------------------------------------------------
3859 * indent-tabs-mode: t