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
33 $Id: codegen.c 2997 2005-07-12 08:39:17Z twisti $
47 #include "vm/jit/powerpc/arch.h"
48 #include "vm/jit/powerpc/codegen.h"
49 #include "vm/jit/powerpc/types.h"
51 #include "cacao/cacao.h"
52 #include "native/native.h"
53 #include "vm/builtin.h"
54 #include "vm/global.h"
55 #include "vm/loader.h"
56 #include "vm/stringlocal.h"
57 #include "vm/tables.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/codegen.inc"
60 #include "vm/jit/jit.h"
63 # include "vm/jit/lsra.inc"
66 #include "vm/jit/parse.h"
67 #include "vm/jit/patcher.h"
68 #include "vm/jit/reg.h"
69 #include "vm/jit/reg.inc"
73 void asm_cacheflush(void *, long);
75 /* #include <architecture/ppc/cframe.h> */
77 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
78 void thread_restartcriticalsection(void *u)
80 /* XXX set pc to restart address */
84 s4 *codegen_trace_args( methodinfo *m, codegendata *cd, registerdata *rd,
85 s4 *mcodeptr, s4 parentargs_base, bool nativestub);
87 /* codegen *********************************************************************
89 Generates machine code.
91 *******************************************************************************/
93 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
95 s4 len, s1, s2, s3, d, disp;
105 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
106 builtintable_entry *bte;
115 /* space to save used callee saved registers */
117 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
118 savedregs_num += 2 * (FLT_SAV_CNT - rd->savfltreguse);
120 parentargs_base = rd->memuse + savedregs_num;
122 #if defined(USE_THREADS)
123 /* space to save argument of monitor_enter and Return Values to survive */
124 /* monitor_exit. The stack position for the argument can not be shared */
125 /* with place to save the return register on PPC, since both values */
127 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
128 /* reserve 2 slots for long/double return values for monitorexit */
130 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
131 parentargs_base += 3;
133 parentargs_base += 2;
138 /* create method header */
140 parentargs_base = (parentargs_base + 3) & ~3;
142 (void) dseg_addaddress(cd, m); /* MethodPointer */
143 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
145 #if defined(USE_THREADS)
146 /* IsSync contains the offset relative to the stack pointer for the
147 argument of monitor_exit used in the exception handler. Since the
148 offset could be zero and give a wrong meaning of the flag it is
152 if (checksync && (m->flags & ACC_SYNCHRONIZED))
153 (void) dseg_adds4(cd, (rd->memuse + 1) * 4); /* IsSync */
156 (void) dseg_adds4(cd, 0); /* IsSync */
158 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
159 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
160 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
162 dseg_addlinenumbertablesize(cd);
164 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
166 /* create exception table */
168 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
169 dseg_addtarget(cd, ex->start);
170 dseg_addtarget(cd, ex->end);
171 dseg_addtarget(cd, ex->handler);
172 (void) dseg_addaddress(cd, ex->catchtype.cls);
175 /* initialize mcode variables */
177 mcodeptr = (s4 *) cd->mcodebase;
178 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
179 MCODECHECK(128 + m->paramcount);
181 /* create stack frame (if necessary) */
183 if (!m->isleafmethod) {
185 M_AST(REG_ITMP3, REG_SP, LA_LR_OFFSET);
188 if (parentargs_base) {
189 M_STWU(REG_SP, REG_SP, -parentargs_base * 4);
192 /* save return address and used callee saved registers */
195 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
196 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
198 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
199 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
202 /* take arguments out of register or stack frame */
206 for (p = 0, l = 0; p < md->paramcount; p++) {
207 t = md->paramtypes[p].type;
208 var = &(rd->locals[l][t]);
210 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
214 s1 = md->params[p].regoff;
215 if (IS_INT_LNG_TYPE(t)) { /* integer args */
216 if (IS_2_WORD_TYPE(t))
217 s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
218 rd->argintregs[GET_HIGH_REG(s1)]);
220 s2 = rd->argintregs[s1];
221 if (!md->params[p].inmemory) { /* register arguments */
222 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
223 M_TINTMOVE(t, s2, var->regoff);
225 } else { /* reg arg -> spilled */
226 if (IS_2_WORD_TYPE(t)) {
227 M_IST(GET_HIGH_REG(s2), REG_SP, var->regoff * 4);
228 M_IST(GET_LOW_REG(s2), REG_SP, var->regoff * 4 + 4);
230 M_IST(s2, REG_SP, var->regoff * 4);
234 } else { /* stack arguments */
235 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
236 if (IS_2_WORD_TYPE(t)) {
237 M_ILD(GET_HIGH_REG(var->regoff), REG_SP,
238 (parentargs_base + s1) * 4);
239 M_ILD(GET_LOW_REG(var->regoff), REG_SP,
240 (parentargs_base + s1) * 4 + 4);
242 M_ILD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
245 } else { /* stack arg -> spilled */
247 M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4);
248 M_IST(REG_ITMP1, REG_SP, var->regoff * 4);
249 if (IS_2_WORD_TYPE(t)) {
250 M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4 +4);
251 M_IST(REG_ITMP1, REG_SP, var->regoff * 4 + 4);
254 /* Reuse Memory Position on Caller Stack */
255 var->regoff = parentargs_base + s1;
260 } else { /* floating args */
261 if (!md->params[p].inmemory) { /* register arguments */
262 s2 = rd->argfltregs[s1];
263 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
264 M_FLTMOVE(s2, var->regoff);
266 } else { /* reg arg -> spilled */
267 if (IS_2_WORD_TYPE(t))
268 M_DST(s2, REG_SP, var->regoff * 4);
270 M_FST(s2, REG_SP, var->regoff * 4);
273 } else { /* stack arguments */
274 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
275 if (IS_2_WORD_TYPE(t))
276 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
279 M_FLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
281 } else { /* stack-arg -> spilled */
283 if (IS_2_WORD_TYPE(t)) {
284 M_DLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
285 M_DST(REG_FTMP1, REG_SP, var->regoff * 4);
286 var->regoff = parentargs_base + s1;
289 M_FLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
290 M_FST(REG_FTMP1, REG_SP, var->regoff * 4);
293 /* Reuse Memory Position on Caller Stack */
294 var->regoff = parentargs_base + s1;
301 /* save monitorenter argument */
303 #if defined(USE_THREADS)
304 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
305 /* stack offset for monitor argument */
311 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT * 4 + FLT_ARG_CNT * 8));
313 for (p = 0; p < INT_ARG_CNT; p++)
314 M_IST(rd->argintregs[p], REG_SP, p * 4);
316 for (p = 0; p < FLT_ARG_CNT * 2; p += 2)
317 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
319 s1 += INT_ARG_CNT + FLT_ARG_CNT;
323 /* decide which monitor enter function to call */
325 if (m->flags & ACC_STATIC) {
326 p = dseg_addaddress(cd, m->class);
327 M_ALD(REG_ITMP1, REG_PV, p);
328 M_AST(REG_ITMP1, REG_SP, s1 * 4);
329 M_MOV(REG_ITMP1, rd->argintregs[0]);
330 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
331 M_ALD(REG_ITMP3, REG_PV, p);
336 M_TST(rd->argintregs[0]);
338 codegen_addxnullrefs(cd, mcodeptr);
339 M_AST(rd->argintregs[0], REG_SP, s1 * 4);
340 p = dseg_addaddress(cd, BUILTIN_monitorenter);
341 M_ALD(REG_ITMP3, REG_PV, p);
348 for (p = 0; p < INT_ARG_CNT; p++)
349 M_ILD(rd->argintregs[p], REG_SP, p * 4);
351 for (p = 0; p < FLT_ARG_CNT; p++)
352 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
355 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
361 /* call trace function */
364 mcodeptr = codegen_trace_args(m, cd, rd, mcodeptr, parentargs_base, false);
366 } /* if (runverbose) */
369 /* end of header generation */
371 /* walk through all basic blocks */
372 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
374 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
376 if (bptr->flags >= BBREACHED) {
378 /* branch resolving */
382 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
383 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
389 /* copy interface registers to their destination */
397 while (src != NULL) {
399 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
400 /* d = reg_of_var(m, src, REG_ITMP1); */
401 if (!(src->flags & INMEMORY))
405 M_INTMOVE(REG_ITMP1, d);
406 store_reg_to_var_int(src, d);
412 while (src != NULL) {
414 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
415 d = reg_of_var(rd, src, REG_ITMP1);
416 M_INTMOVE(REG_ITMP1, d);
417 store_reg_to_var_int(src, d);
419 if (src->type == TYPE_LNG)
420 d = reg_of_var(rd, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
422 d = reg_of_var(rd, src, REG_IFTMP);
423 if ((src->varkind != STACKVAR)) {
425 if (IS_FLT_DBL_TYPE(s2)) {
426 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
427 s1 = rd->interfaces[len][s2].regoff;
430 if (IS_2_WORD_TYPE(s2)) {
432 4 * rd->interfaces[len][s2].regoff);
435 4 * rd->interfaces[len][s2].regoff);
438 store_reg_to_var_flt(src, d);
440 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
441 s1 = rd->interfaces[len][s2].regoff;
444 if (IS_2_WORD_TYPE(s2)) {
445 M_ILD(GET_HIGH_REG(d), REG_SP,
446 4 * rd->interfaces[len][s2].regoff);
447 M_ILD(GET_LOW_REG(d), REG_SP,
448 4 * rd->interfaces[len][s2].regoff + 4);
451 4 * rd->interfaces[len][s2].regoff);
454 store_reg_to_var_int(src, d);
464 /* walk through all instructions */
469 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
470 if (iptr->line != currentline) {
471 dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
472 currentline = iptr->line;
475 MCODECHECK(64); /* an instruction usually needs < 64 words */
478 case ICMD_NOP: /* ... ==> ... */
479 case ICMD_INLINE_START:
480 case ICMD_INLINE_END:
483 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
485 var_to_reg_int(s1, src, REG_ITMP1);
488 codegen_addxnullrefs(cd, mcodeptr);
491 /* constant operations ************************************************/
493 case ICMD_ICONST: /* ... ==> ..., constant */
494 /* op1 = 0, val.i = constant */
496 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
497 ICONST(d, iptr->val.i);
498 store_reg_to_var_int(iptr->dst, d);
501 case ICMD_LCONST: /* ... ==> ..., constant */
502 /* op1 = 0, val.l = constant */
504 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
505 LCONST(d, iptr->val.l);
506 store_reg_to_var_int(iptr->dst, d);
509 case ICMD_FCONST: /* ... ==> ..., constant */
510 /* op1 = 0, val.f = constant */
512 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
513 a = dseg_addfloat(cd, iptr->val.f);
515 store_reg_to_var_flt(iptr->dst, d);
518 case ICMD_DCONST: /* ... ==> ..., constant */
519 /* op1 = 0, val.d = constant */
521 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
522 a = dseg_adddouble(cd, iptr->val.d);
524 store_reg_to_var_flt(iptr->dst, d);
527 case ICMD_ACONST: /* ... ==> ..., constant */
528 /* op1 = 0, val.a = constant */
530 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
531 ICONST(d, (u4) iptr->val.a);
532 store_reg_to_var_int(iptr->dst, d);
536 /* load/store operations **********************************************/
538 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
539 case ICMD_LLOAD: /* op1 = local variable */
542 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
543 if (IS_2_WORD_TYPE(var->type)) /* TYPE_LNG */
544 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
546 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
547 if ((iptr->dst->varkind == LOCALVAR) &&
548 (iptr->dst->varnum == iptr->op1))
551 if (var->flags & INMEMORY) {
552 if (IS_2_WORD_TYPE(var->type)) {
553 M_ILD(GET_HIGH_REG(d), REG_SP, var->regoff * 4);
554 M_ILD(GET_LOW_REG(d), REG_SP, var->regoff * 4 + 4);
556 M_ILD(d, REG_SP, var->regoff * 4);
559 M_TINTMOVE(var->type, var->regoff, d);
561 store_reg_to_var_int(iptr->dst, d);
564 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
565 case ICMD_DLOAD: /* op1 = local variable */
567 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
568 if ((iptr->dst->varkind == LOCALVAR) &&
569 (iptr->dst->varnum == iptr->op1))
571 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
572 if (var->flags & INMEMORY)
573 if (IS_2_WORD_TYPE(var->type))
574 M_DLD(d, REG_SP, 4 * var->regoff);
576 M_FLD(d, REG_SP, 4 * var->regoff);
578 M_FLTMOVE(var->regoff, d);
580 store_reg_to_var_flt(iptr->dst, d);
584 case ICMD_ISTORE: /* ..., value ==> ... */
585 case ICMD_LSTORE: /* op1 = local variable */
588 if ((src->varkind == LOCALVAR) &&
589 (src->varnum == iptr->op1))
591 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
592 if (var->flags & INMEMORY) {
593 if (IS_2_WORD_TYPE(var->type)) {
594 var_to_reg_int(s1, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
595 M_IST(GET_HIGH_REG(s1), REG_SP, var->regoff * 4);
596 M_IST(GET_LOW_REG(s1), REG_SP, var->regoff * 4 + 4);
598 var_to_reg_int(s1, src, REG_ITMP1);
599 M_IST(s1, REG_SP, var->regoff * 4);
603 var_to_reg_int(s1, src, var->regoff);
604 M_TINTMOVE(var->type, s1, var->regoff);
608 case ICMD_FSTORE: /* ..., value ==> ... */
609 case ICMD_DSTORE: /* op1 = local variable */
611 if ((src->varkind == LOCALVAR) &&
612 (src->varnum == iptr->op1))
614 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
615 if (var->flags & INMEMORY) {
616 var_to_reg_flt(s1, src, REG_FTMP1);
617 if (var->type == TYPE_DBL)
618 M_DST(s1, REG_SP, 4 * var->regoff);
620 M_FST(s1, REG_SP, 4 * var->regoff);
622 var_to_reg_flt(s1, src, var->regoff);
623 M_FLTMOVE(s1, var->regoff);
628 /* pop/dup/swap operations ********************************************/
630 /* attention: double and longs are only one entry in CACAO ICMDs */
632 case ICMD_POP: /* ..., value ==> ... */
633 case ICMD_POP2: /* ..., value, value ==> ... */
636 case ICMD_DUP: /* ..., a ==> ..., a, a */
637 M_COPY(src, iptr->dst);
640 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
642 M_COPY(src, iptr->dst);
643 M_COPY(src->prev, iptr->dst->prev);
644 M_COPY(iptr->dst, iptr->dst->prev->prev);
647 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
649 M_COPY(src, iptr->dst);
650 M_COPY(src->prev, iptr->dst->prev);
651 M_COPY(src->prev->prev, iptr->dst->prev->prev);
652 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
655 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
657 M_COPY(src, iptr->dst);
658 M_COPY(src->prev, iptr->dst->prev);
661 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
663 M_COPY(src, iptr->dst);
664 M_COPY(src->prev, iptr->dst->prev);
665 M_COPY(src->prev->prev, iptr->dst->prev->prev);
666 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
667 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
670 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
672 M_COPY(src, iptr->dst);
673 M_COPY(src->prev, iptr->dst->prev);
674 M_COPY(src->prev->prev, iptr->dst->prev->prev);
675 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
676 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
677 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
680 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
682 M_COPY(src, iptr->dst->prev);
683 M_COPY(src->prev, iptr->dst);
687 /* integer operations *************************************************/
689 case ICMD_INEG: /* ..., value ==> ..., - value */
691 var_to_reg_int(s1, src, REG_ITMP1);
692 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
694 store_reg_to_var_int(iptr->dst, d);
697 case ICMD_LNEG: /* ..., value ==> ..., - value */
699 var_to_reg_int(s1, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
700 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
701 M_SUBFIC(GET_LOW_REG(s1), 0, GET_LOW_REG(d));
702 M_SUBFZE(GET_HIGH_REG(s1), GET_HIGH_REG(d));
703 store_reg_to_var_int(iptr->dst, d);
706 case ICMD_I2L: /* ..., value ==> ..., value */
708 var_to_reg_int(s1, src, REG_ITMP2);
709 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
710 M_INTMOVE(s1, GET_LOW_REG(d));
711 M_SRA_IMM(GET_LOW_REG(d), 31, GET_HIGH_REG(d));
712 store_reg_to_var_int(iptr->dst, d);
715 case ICMD_L2I: /* ..., value ==> ..., value */
717 var_to_reg_int_low(s1, src, REG_ITMP2);
718 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
720 store_reg_to_var_int(iptr->dst, d);
723 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
725 var_to_reg_int(s1, src, REG_ITMP1);
726 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
728 store_reg_to_var_int(iptr->dst, d);
731 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
733 var_to_reg_int(s1, src, REG_ITMP1);
734 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
736 store_reg_to_var_int(iptr->dst, d);
739 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
741 var_to_reg_int(s1, src, REG_ITMP1);
742 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
744 store_reg_to_var_int(iptr->dst, d);
748 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
750 var_to_reg_int(s1, src->prev, REG_ITMP1);
751 var_to_reg_int(s2, src, REG_ITMP2);
752 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
754 store_reg_to_var_int(iptr->dst, d);
757 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
758 /* val.i = constant */
760 var_to_reg_int(s1, src, REG_ITMP1);
761 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
762 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
763 M_IADD_IMM(s1, iptr->val.i, d);
765 ICONST(REG_ITMP2, iptr->val.i);
766 M_IADD(s1, REG_ITMP2, d);
768 store_reg_to_var_int(iptr->dst, d);
771 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
773 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
774 var_to_reg_int_low(s2, src, REG_ITMP2);
775 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
776 M_ADDC(s1, s2, GET_LOW_REG(d));
777 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
778 var_to_reg_int_high(s2, src, REG_ITMP3);
779 M_ADDE(s1, s2, GET_HIGH_REG(d));
780 store_reg_to_var_int(iptr->dst, d);
783 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
784 /* val.l = constant */
786 s3 = iptr->val.l & 0xffffffff;
787 var_to_reg_int_low(s1, src, REG_ITMP1);
788 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
789 if ((s3 >= -32768) && (s3 <= 32767)) {
790 M_ADDIC(s1, s3, GET_LOW_REG(d));
793 ICONST(REG_ITMP2, s3);
794 M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
797 var_to_reg_int_high(s1, src, REG_ITMP1);
798 s3 = iptr->val.l >> 32;
800 M_ADDME(s1, GET_HIGH_REG(d));
802 M_ADDZE(s1, GET_HIGH_REG(d));
804 ICONST(REG_ITMP3, s3);
805 M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
807 store_reg_to_var_int(iptr->dst, d);
810 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
812 var_to_reg_int(s1, src->prev, REG_ITMP1);
813 var_to_reg_int(s2, src, REG_ITMP2);
814 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
816 store_reg_to_var_int(iptr->dst, d);
819 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
820 /* val.i = constant */
822 var_to_reg_int(s1, src, REG_ITMP1);
823 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
824 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
825 M_IADD_IMM(s1, -iptr->val.i, d);
827 ICONST(REG_ITMP2, -iptr->val.i);
828 M_IADD(s1, REG_ITMP2, d);
830 store_reg_to_var_int(iptr->dst, d);
833 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
835 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
836 var_to_reg_int_low(s2, src, REG_ITMP2);
837 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
838 M_SUBC(s1, s2, GET_LOW_REG(d));
839 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
840 var_to_reg_int_high(s2, src, REG_ITMP3);
841 M_SUBE(s1, s2, GET_HIGH_REG(d));
842 store_reg_to_var_int(iptr->dst, d);
845 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
846 /* val.l = constant */
848 s3 = (-iptr->val.l) & 0xffffffff;
849 var_to_reg_int_low(s1, src, REG_ITMP1);
850 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
851 if ((s3 >= -32768) && (s3 <= 32767)) {
852 M_ADDIC(s1, s3, GET_LOW_REG(d));
854 ICONST(REG_ITMP2, s3);
855 M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
857 var_to_reg_int_high(s1, src, REG_ITMP1);
858 s3 = (-iptr->val.l) >> 32;
860 M_ADDME(s1, GET_HIGH_REG(d));
862 M_ADDZE(s1, GET_HIGH_REG(d));
864 ICONST(REG_ITMP3, s3);
865 M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
867 store_reg_to_var_int(iptr->dst, d);
870 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
872 var_to_reg_int(s1, src->prev, REG_ITMP1);
873 var_to_reg_int(s2, src, REG_ITMP2);
876 codegen_addxdivrefs(cd, mcodeptr);
877 M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
878 M_CMP(REG_ITMP3, s1);
879 d = reg_of_var(rd, iptr->dst, REG_ITMP3); /* does not change flags*/
880 M_BNE(3 + (s1 != d));
882 M_BNE(1 + (s1 != d));
886 store_reg_to_var_int(iptr->dst, d);
889 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
891 var_to_reg_int(s1, src->prev, REG_ITMP1);
892 var_to_reg_int(s2, src, REG_ITMP2);
895 codegen_addxdivrefs(cd, mcodeptr);
896 M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
897 M_CMP(REG_ITMP3, s1);
898 d = reg_of_var(rd, iptr->dst, REG_ITMP3); /* does not change flags*/
904 M_IDIV(s1, s2, REG_ITMP3);
905 M_IMUL(REG_ITMP3, s2, REG_ITMP3);
906 M_ISUB(s1, REG_ITMP3, d);
907 store_reg_to_var_int(iptr->dst, d);
910 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
911 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
916 var_to_reg_int(s2, src, PACK_REGS(REG_ITMP1, REG_ITMP2));
917 M_OR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
919 codegen_addxdivrefs(cd, mcodeptr);
921 s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[1].regoff)],
922 rd->argintregs[GET_HIGH_REG(md->params[1].regoff)]);
923 M_TINTMOVE(TYPE_LNG, s2, s3);
925 var_to_reg_int(s1, src->prev, PACK_REGS(REG_ITMP1, REG_ITMP2));
926 s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[0].regoff)],
927 rd->argintregs[GET_HIGH_REG(md->params[0].regoff)]);
928 M_TINTMOVE(TYPE_LNG, s1, s3);
930 disp = dseg_addaddress(cd, bte->fp);
931 M_ALD(REG_ITMP1, REG_PV, disp);
935 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_RESULT2, REG_RESULT));
936 M_TINTMOVE(TYPE_LNG, PACK_REGS(REG_RESULT2, REG_RESULT), d);
937 store_reg_to_var_int(iptr->dst, d);
940 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
942 var_to_reg_int(s1, src->prev, REG_ITMP1);
943 var_to_reg_int(s2, src, REG_ITMP2);
944 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
946 store_reg_to_var_int(iptr->dst, d);
949 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
950 /* val.i = constant */
952 var_to_reg_int(s1, src, REG_ITMP1);
953 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
954 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
955 M_IMUL_IMM(s1, iptr->val.i, d);
958 ICONST(REG_ITMP2, iptr->val.i);
959 M_IMUL(s1, REG_ITMP2, d);
961 store_reg_to_var_int(iptr->dst, d);
964 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
966 var_to_reg_int(s1, src, REG_ITMP1);
967 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
968 M_SRA_IMM(s1, iptr->val.i, d);
970 store_reg_to_var_int(iptr->dst, d);
973 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
975 var_to_reg_int(s1, src->prev, REG_ITMP1);
976 var_to_reg_int(s2, src, REG_ITMP2);
977 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
978 M_AND_IMM(s2, 0x1f, REG_ITMP3);
979 M_SLL(s1, REG_ITMP3, d);
980 store_reg_to_var_int(iptr->dst, d);
983 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
984 /* val.i = constant */
986 var_to_reg_int(s1, src, REG_ITMP1);
987 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
988 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
989 store_reg_to_var_int(iptr->dst, d);
992 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
994 var_to_reg_int(s1, src->prev, REG_ITMP1);
995 var_to_reg_int(s2, src, REG_ITMP2);
996 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
997 M_AND_IMM(s2, 0x1f, REG_ITMP3);
998 M_SRA(s1, REG_ITMP3, d);
999 store_reg_to_var_int(iptr->dst, d);
1002 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1003 /* val.i = constant */
1005 var_to_reg_int(s1, src, REG_ITMP1);
1006 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1007 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1008 store_reg_to_var_int(iptr->dst, d);
1011 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1013 var_to_reg_int(s1, src->prev, REG_ITMP1);
1014 var_to_reg_int(s2, src, REG_ITMP2);
1015 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1016 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1017 M_SRL(s1, REG_ITMP2, d);
1018 store_reg_to_var_int(iptr->dst, d);
1021 case ICMD_IUSHRCONST: /* ..., 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 & 0x1f)
1027 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1030 store_reg_to_var_int(iptr->dst, d);
1033 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1035 var_to_reg_int(s1, src->prev, REG_ITMP1);
1036 var_to_reg_int(s2, src, REG_ITMP2);
1037 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1039 store_reg_to_var_int(iptr->dst, d);
1042 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1043 /* val.i = constant */
1045 var_to_reg_int(s1, src, REG_ITMP1);
1046 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1047 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1048 M_AND_IMM(s1, iptr->val.i, d);
1051 else if (iptr->val.i == 0xffffff) {
1052 M_RLWINM(s1, 0, 8, 31, d);
1056 ICONST(REG_ITMP2, iptr->val.i);
1057 M_AND(s1, REG_ITMP2, d);
1059 store_reg_to_var_int(iptr->dst, d);
1062 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1064 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1065 var_to_reg_int_low(s2, src, REG_ITMP2);
1066 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1067 M_AND(s1, s2, GET_LOW_REG(d));
1068 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1069 var_to_reg_int_high(s2, src, REG_ITMP3);
1070 M_AND(s1, s2, GET_HIGH_REG(d));
1071 store_reg_to_var_int(iptr->dst, d);
1074 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1075 /* val.l = constant */
1077 s3 = iptr->val.l & 0xffffffff;
1078 var_to_reg_int_low(s1, src, REG_ITMP1);
1079 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1080 if ((s3 >= 0) && (s3 <= 65535)) {
1081 M_AND_IMM(s1, s3, GET_LOW_REG(d));
1083 ICONST(REG_ITMP2, s3);
1084 M_AND(s1, REG_ITMP2, GET_LOW_REG(d));
1086 var_to_reg_int_high(s1, src, REG_ITMP1);
1087 s3 = iptr->val.l >> 32;
1088 if ((s3 >= 0) && (s3 <= 65535)) {
1089 M_AND_IMM(s1, s3, GET_HIGH_REG(d));
1092 ICONST(REG_ITMP3, s3);
1093 M_AND(s1, REG_ITMP3, GET_HIGH_REG(d));
1095 store_reg_to_var_int(iptr->dst, d);
1098 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1099 /* val.i = constant */
1101 var_to_reg_int(s1, src, REG_ITMP1);
1102 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1103 M_MOV(s1, REG_ITMP2);
1105 M_BGE(1 + 2*(iptr->val.i >= 32768));
1106 if (iptr->val.i >= 32768) {
1107 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1108 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1109 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1111 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1113 int b=0, m = iptr->val.i;
1116 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1118 M_ISUB(s1, REG_ITMP2, d);
1119 store_reg_to_var_int(iptr->dst, d);
1122 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1124 var_to_reg_int(s1, src->prev, REG_ITMP1);
1125 var_to_reg_int(s2, src, REG_ITMP2);
1126 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1128 store_reg_to_var_int(iptr->dst, d);
1131 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1132 /* val.i = constant */
1134 var_to_reg_int(s1, src, REG_ITMP1);
1135 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1136 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1137 M_OR_IMM(s1, iptr->val.i, d);
1140 ICONST(REG_ITMP2, iptr->val.i);
1141 M_OR(s1, REG_ITMP2, d);
1143 store_reg_to_var_int(iptr->dst, d);
1146 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1148 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1149 var_to_reg_int_low(s2, src, REG_ITMP2);
1150 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1151 M_OR(s1, s2, GET_LOW_REG(d));
1152 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1153 var_to_reg_int_high(s2, src, REG_ITMP3);
1154 M_OR(s1, s2, GET_HIGH_REG(d));
1155 store_reg_to_var_int(iptr->dst, d);
1158 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1159 /* val.l = constant */
1161 s3 = iptr->val.l & 0xffffffff;
1162 var_to_reg_int_low(s1, src, REG_ITMP1);
1163 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1164 if ((s3 >= 0) && (s3 <= 65535)) {
1165 M_OR_IMM(s1, s3, GET_LOW_REG(d));
1167 ICONST(REG_ITMP2, s3);
1168 M_OR(s1, REG_ITMP2, GET_LOW_REG(d));
1170 var_to_reg_int_high(s1, src, REG_ITMP1);
1171 s3 = iptr->val.l >> 32;
1172 if ((s3 >= 0) && (s3 <= 65535)) {
1173 M_OR_IMM(s1, s3, GET_HIGH_REG(d));
1175 ICONST(REG_ITMP3, s3);
1176 M_OR(s1, REG_ITMP3, GET_HIGH_REG(d));
1178 store_reg_to_var_int(iptr->dst, d);
1181 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1183 var_to_reg_int(s1, src->prev, REG_ITMP1);
1184 var_to_reg_int(s2, src, REG_ITMP2);
1185 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1187 store_reg_to_var_int(iptr->dst, d);
1190 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1191 /* val.i = constant */
1193 var_to_reg_int(s1, src, REG_ITMP1);
1194 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1195 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1196 M_XOR_IMM(s1, iptr->val.i, d);
1199 ICONST(REG_ITMP2, iptr->val.i);
1200 M_XOR(s1, REG_ITMP2, d);
1202 store_reg_to_var_int(iptr->dst, d);
1205 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1207 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1208 var_to_reg_int_low(s2, src, REG_ITMP2);
1209 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1210 M_XOR(s1, s2, GET_LOW_REG(d));
1211 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1212 var_to_reg_int_high(s2, src, REG_ITMP3);
1213 M_XOR(s1, s2, GET_HIGH_REG(d));
1214 store_reg_to_var_int(iptr->dst, d);
1217 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1218 /* val.l = constant */
1220 s3 = iptr->val.l & 0xffffffff;
1221 var_to_reg_int_low(s1, src, REG_ITMP1);
1222 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1223 if ((s3 >= 0) && (s3 <= 65535)) {
1224 M_XOR_IMM(s1, s3, GET_LOW_REG(d));
1226 ICONST(REG_ITMP2, s3);
1227 M_XOR(s1, REG_ITMP2, GET_LOW_REG(d));
1229 var_to_reg_int_high(s1, src, REG_ITMP1);
1230 s3 = iptr->val.l >> 32;
1231 if ((s3 >= 0) && (s3 <= 65535)) {
1232 M_XOR_IMM(s1, s3, GET_HIGH_REG(d));
1234 ICONST(REG_ITMP3, s3);
1235 M_XOR(s1, REG_ITMP3, GET_HIGH_REG(d));
1237 store_reg_to_var_int(iptr->dst, d);
1240 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1241 /*******************************************************************
1242 TODO: CHANGE THIS TO A VERSION THAT WORKS !!!
1243 *******************************************************************/
1244 var_to_reg_int_high(s1, src->prev, REG_ITMP3);
1245 var_to_reg_int_high(s2, src, REG_ITMP2);
1246 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1248 int tempreg = false;
1252 if (src->prev->flags & INMEMORY) {
1253 tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
1255 tempreg = tempreg || (d == GET_HIGH_REG(src->prev->regoff))
1256 || (d == GET_LOW_REG(src->prev->regoff));
1258 if (src->flags & INMEMORY) {
1259 tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
1261 tempreg = tempreg || (d == GET_HIGH_REG(src->regoff))
1262 || (d == GET_LOW_REG(src->regoff));
1265 dreg = tempreg ? REG_ITMP1 : d;
1266 M_IADD_IMM(REG_ZERO, 1, dreg);
1271 var_to_reg_int_low(s1, src->prev, REG_ITMP3);
1272 var_to_reg_int_low(s2, src, REG_ITMP2);
1276 M_IADD_IMM(dreg, -1, dreg);
1277 M_IADD_IMM(dreg, -1, dreg);
1278 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1279 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1282 store_reg_to_var_int(iptr->dst, d);
1285 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1286 /* op1 = variable, val.i = constant */
1288 var = &(rd->locals[iptr->op1][TYPE_INT]);
1289 if (var->flags & INMEMORY) {
1291 M_ILD(s1, REG_SP, var->regoff * 4);
1299 M_ADDIS(s1, m>>16, s1);
1301 M_IADD_IMM(s1, m&0xffff, s1);
1303 if (var->flags & INMEMORY)
1304 M_IST(s1, REG_SP, var->regoff * 4);
1308 /* floating operations ************************************************/
1310 case ICMD_FNEG: /* ..., value ==> ..., - value */
1312 var_to_reg_flt(s1, src, REG_FTMP1);
1313 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1315 store_reg_to_var_flt(iptr->dst, d);
1318 case ICMD_DNEG: /* ..., value ==> ..., - value */
1320 var_to_reg_flt(s1, src, REG_FTMP1);
1321 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1323 store_reg_to_var_flt(iptr->dst, d);
1326 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1328 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1329 var_to_reg_flt(s2, src, REG_FTMP2);
1330 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1332 store_reg_to_var_flt(iptr->dst, d);
1335 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1337 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1338 var_to_reg_flt(s2, src, REG_FTMP2);
1339 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1341 store_reg_to_var_flt(iptr->dst, d);
1344 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1346 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1347 var_to_reg_flt(s2, src, REG_FTMP2);
1348 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1350 store_reg_to_var_flt(iptr->dst, d);
1353 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1355 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1356 var_to_reg_flt(s2, src, REG_FTMP2);
1357 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1359 store_reg_to_var_flt(iptr->dst, d);
1362 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1364 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1365 var_to_reg_flt(s2, src, REG_FTMP2);
1366 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1368 store_reg_to_var_flt(iptr->dst, d);
1371 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1373 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1374 var_to_reg_flt(s2, src, REG_FTMP2);
1375 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1377 store_reg_to_var_flt(iptr->dst, d);
1380 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1382 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1383 var_to_reg_flt(s2, src, REG_FTMP2);
1384 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1386 store_reg_to_var_flt(iptr->dst, d);
1389 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1391 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1392 var_to_reg_flt(s2, src, REG_FTMP2);
1393 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1395 store_reg_to_var_flt(iptr->dst, d);
1398 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1400 var_to_reg_flt(s1, src, REG_FTMP1);
1401 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1403 a = dseg_addfloat(cd, 0.0);
1404 M_FLD(REG_FTMP2, REG_PV, a);
1405 M_FCMPU(s1, REG_FTMP2);
1407 a = dseg_adds4(cd, 0);
1408 M_CVTDL_C(s1, REG_FTMP1);
1409 M_LDA (REG_ITMP1, REG_PV, a);
1410 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1411 M_ILD (d, REG_PV, a);
1412 store_reg_to_var_int(iptr->dst, d);
1415 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1417 var_to_reg_flt(s1, src, REG_FTMP1);
1418 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1420 store_reg_to_var_flt(iptr->dst, d);
1423 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1425 var_to_reg_flt(s1, src, REG_FTMP1);
1426 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1428 store_reg_to_var_flt(iptr->dst, d);
1431 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1433 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1434 var_to_reg_flt(s2, src, REG_FTMP2);
1435 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1437 M_IADD_IMM(0, -1, d);
1440 M_IADD_IMM(0, 0, d);
1442 M_IADD_IMM(0, 1, d);
1443 store_reg_to_var_int(iptr->dst, d);
1446 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1448 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1449 var_to_reg_flt(s2, src, REG_FTMP2);
1450 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1452 M_IADD_IMM(0, 1, d);
1455 M_IADD_IMM(0, 0, d);
1457 M_IADD_IMM(0, -1, d);
1458 store_reg_to_var_int(iptr->dst, d);
1462 /* memory operations **************************************************/
1464 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1466 var_to_reg_int(s1, src, REG_ITMP1);
1467 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1468 gen_nullptr_check(s1);
1469 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1470 store_reg_to_var_int(iptr->dst, d);
1473 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1475 var_to_reg_int(s1, src->prev, REG_ITMP1);
1476 var_to_reg_int(s2, src, REG_ITMP2);
1477 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1478 if (iptr->op1 == 0) {
1479 gen_nullptr_check(s1);
1482 M_SLL_IMM(s2, 2, REG_ITMP2);
1483 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1484 M_LWZX(d, s1, REG_ITMP2);
1485 store_reg_to_var_int(iptr->dst, d);
1488 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1490 var_to_reg_int(s1, src->prev, REG_ITMP1);
1491 var_to_reg_int(s2, src, REG_ITMP2);
1492 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1493 if (iptr->op1 == 0) {
1494 gen_nullptr_check(s1);
1497 M_SLL_IMM(s2, 3, REG_ITMP2);
1498 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1499 M_ILD(GET_HIGH_REG(d), REG_ITMP2, OFFSET(java_longarray, data[0]));
1500 M_ILD(GET_LOW_REG(d), REG_ITMP2, OFFSET(java_longarray,
1502 store_reg_to_var_int(iptr->dst, d);
1505 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1507 var_to_reg_int(s1, src->prev, REG_ITMP1);
1508 var_to_reg_int(s2, src, REG_ITMP2);
1509 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1510 if (iptr->op1 == 0) {
1511 gen_nullptr_check(s1);
1514 M_SLL_IMM(s2, 2, REG_ITMP2);
1515 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1516 M_LWZX(d, s1, REG_ITMP2);
1517 store_reg_to_var_int(iptr->dst, d);
1520 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1522 var_to_reg_int(s1, src->prev, REG_ITMP1);
1523 var_to_reg_int(s2, src, REG_ITMP2);
1524 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1525 if (iptr->op1 == 0) {
1526 gen_nullptr_check(s1);
1529 M_SLL_IMM(s2, 2, REG_ITMP2);
1530 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1531 M_LFSX(d, s1, REG_ITMP2);
1532 store_reg_to_var_flt(iptr->dst, d);
1535 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1537 var_to_reg_int(s1, src->prev, REG_ITMP1);
1538 var_to_reg_int(s2, src, REG_ITMP2);
1539 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1540 if (iptr->op1 == 0) {
1541 gen_nullptr_check(s1);
1544 M_SLL_IMM(s2, 3, REG_ITMP2);
1545 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1546 M_LFDX(d, s1, REG_ITMP2);
1547 store_reg_to_var_flt(iptr->dst, d);
1550 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1552 var_to_reg_int(s1, src->prev, REG_ITMP1);
1553 var_to_reg_int(s2, src, REG_ITMP2);
1554 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1555 if (iptr->op1 == 0) {
1556 gen_nullptr_check(s1);
1559 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1560 M_LBZX(d, s1, REG_ITMP2);
1562 store_reg_to_var_int(iptr->dst, d);
1565 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1567 var_to_reg_int(s1, src->prev, REG_ITMP1);
1568 var_to_reg_int(s2, src, REG_ITMP2);
1569 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1570 if (iptr->op1 == 0) {
1571 gen_nullptr_check(s1);
1574 M_SLL_IMM(s2, 1, REG_ITMP2);
1575 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1576 M_LHAX(d, s1, REG_ITMP2);
1577 store_reg_to_var_int(iptr->dst, d);
1580 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1582 var_to_reg_int(s1, src->prev, REG_ITMP1);
1583 var_to_reg_int(s2, src, REG_ITMP2);
1584 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1585 if (iptr->op1 == 0) {
1586 gen_nullptr_check(s1);
1589 M_SLL_IMM(s2, 1, REG_ITMP2);
1590 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1591 M_LHZX(d, s1, REG_ITMP2);
1592 store_reg_to_var_int(iptr->dst, d);
1595 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1597 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1598 var_to_reg_int(s2, src->prev, REG_ITMP2);
1599 if (iptr->op1 == 0) {
1600 gen_nullptr_check(s1);
1603 var_to_reg_int_high(s3, src, REG_ITMP3);
1604 M_SLL_IMM(s2, 3, REG_ITMP2);
1605 M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
1606 M_STWX(s3, s1, REG_ITMP2);
1607 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1608 var_to_reg_int_low(s3, src, REG_ITMP3);
1609 M_STWX(s3, s1, REG_ITMP2);
1612 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1614 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1615 var_to_reg_int(s2, src->prev, REG_ITMP2);
1616 if (iptr->op1 == 0) {
1617 gen_nullptr_check(s1);
1620 var_to_reg_int(s3, src, REG_ITMP3);
1621 M_SLL_IMM(s2, 2, REG_ITMP2);
1622 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1623 M_STWX(s3, s1, REG_ITMP2);
1626 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1628 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1629 var_to_reg_int(s2, src->prev, REG_ITMP2);
1630 if (iptr->op1 == 0) {
1631 gen_nullptr_check(s1);
1634 var_to_reg_flt(s3, src, REG_FTMP3);
1635 M_SLL_IMM(s2, 2, REG_ITMP2);
1636 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1637 M_STFSX(s3, s1, REG_ITMP2);
1640 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1642 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1643 var_to_reg_int(s2, src->prev, REG_ITMP2);
1644 if (iptr->op1 == 0) {
1645 gen_nullptr_check(s1);
1648 var_to_reg_flt(s3, src, REG_FTMP3);
1649 M_SLL_IMM(s2, 3, REG_ITMP2);
1650 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1651 M_STFDX(s3, s1, REG_ITMP2);
1654 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1656 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1657 var_to_reg_int(s2, src->prev, REG_ITMP2);
1658 if (iptr->op1 == 0) {
1659 gen_nullptr_check(s1);
1662 var_to_reg_int(s3, src, REG_ITMP3);
1663 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1664 M_STBX(s3, s1, REG_ITMP2);
1667 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1669 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1670 var_to_reg_int(s2, src->prev, REG_ITMP2);
1671 if (iptr->op1 == 0) {
1672 gen_nullptr_check(s1);
1675 var_to_reg_int(s3, src, REG_ITMP3);
1676 M_SLL_IMM(s2, 1, REG_ITMP2);
1677 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1678 M_STHX(s3, s1, REG_ITMP2);
1681 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1683 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1684 var_to_reg_int(s2, src->prev, REG_ITMP2);
1685 if (iptr->op1 == 0) {
1686 gen_nullptr_check(s1);
1689 var_to_reg_int(s3, src, REG_ITMP3);
1690 M_SLL_IMM(s2, 1, REG_ITMP2);
1691 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1692 M_STHX(s3, s1, REG_ITMP2);
1696 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1699 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1700 var_to_reg_int(s2, src->prev, REG_ITMP2);
1701 /* if (iptr->op1 == 0) { */
1702 gen_nullptr_check(s1);
1705 var_to_reg_int(s3, src, REG_ITMP3);
1707 M_MOV(s1, rd->argintregs[0]);
1708 M_MOV(s3, rd->argintregs[1]);
1710 disp = dseg_addaddress(cd, bte->fp);
1711 M_ALD(REG_ITMP1, REG_PV, disp);
1716 codegen_addxstorerefs(cd, mcodeptr);
1718 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1719 var_to_reg_int(s2, src->prev, REG_ITMP2);
1720 var_to_reg_int(s3, src, REG_ITMP3);
1721 M_SLL_IMM(s2, 2, REG_ITMP2);
1722 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1723 M_STWX(s3, s1, REG_ITMP2);
1728 case ICMD_GETSTATIC: /* ... ==> ..., value */
1729 /* op1 = type, val.a = field address */
1732 codegen_addpatchref(cd, mcodeptr,
1733 PATCHER_get_putstatic,
1734 (unresolved_field *) iptr->target);
1736 if (opt_showdisassemble)
1742 fieldinfo *fi = iptr->val.a;
1744 if (!fi->class->initialized) {
1745 codegen_addpatchref(cd, mcodeptr,
1746 PATCHER_clinit, fi->class);
1748 if (opt_showdisassemble)
1752 a = (ptrint) &(fi->value);
1755 a = dseg_addaddress(cd, a);
1756 M_ALD(REG_ITMP1, REG_PV, a);
1757 switch (iptr->op1) {
1759 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1760 M_ILD(d, REG_ITMP1, 0);
1761 store_reg_to_var_int(iptr->dst, d);
1764 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1765 M_ILD(GET_HIGH_REG(d), REG_ITMP1, 0);
1766 M_ILD(GET_LOW_REG(d), REG_ITMP1, 4);
1767 store_reg_to_var_int(iptr->dst, d);
1770 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1771 M_ALD(d, REG_ITMP1, 0);
1772 store_reg_to_var_int(iptr->dst, d);
1775 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1776 M_FLD(d, REG_ITMP1, 0);
1777 store_reg_to_var_flt(iptr->dst, d);
1780 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1781 M_DLD(d, REG_ITMP1, 0);
1782 store_reg_to_var_flt(iptr->dst, d);
1787 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1788 /* op1 = type, val.a = field address */
1792 codegen_addpatchref(cd, mcodeptr,
1793 PATCHER_get_putstatic,
1794 (unresolved_field *) iptr->target);
1796 if (opt_showdisassemble)
1802 fieldinfo *fi = iptr->val.a;
1804 if (!fi->class->initialized) {
1805 codegen_addpatchref(cd, mcodeptr,
1806 PATCHER_clinit, fi->class);
1808 if (opt_showdisassemble)
1812 a = (ptrint) &(fi->value);
1815 disp = dseg_addaddress(cd, a);
1816 M_ALD(REG_ITMP1, REG_PV, disp);
1817 switch (iptr->op1) {
1819 var_to_reg_int(s2, src, REG_ITMP2);
1820 M_IST(s2, REG_ITMP1, 0);
1823 var_to_reg_int(s2, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
1824 M_IST(GET_HIGH_REG(s2), REG_ITMP1, 0);
1825 M_IST(GET_LOW_REG(s2), REG_ITMP1, 4);
1828 var_to_reg_int(s2, src, REG_ITMP2);
1829 M_AST(s2, REG_ITMP1, 0);
1832 var_to_reg_flt(s2, src, REG_FTMP2);
1833 M_FST(s2, REG_ITMP1, 0);
1836 var_to_reg_flt(s2, src, REG_FTMP2);
1837 M_DST(s2, REG_ITMP1, 0);
1843 case ICMD_GETFIELD: /* ... ==> ..., value */
1844 /* op1 = type, val.i = field offset */
1846 var_to_reg_int(s1, src, REG_ITMP1);
1847 gen_nullptr_check(s1);
1850 codegen_addpatchref(cd, mcodeptr,
1851 PATCHER_get_putfield,
1852 (unresolved_field *) iptr->target);
1854 if (opt_showdisassemble)
1860 a = ((fieldinfo *) (iptr->val.a))->offset;
1863 switch (iptr->op1) {
1865 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1867 store_reg_to_var_int(iptr->dst, d);
1870 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1871 M_ILD(GET_HIGH_REG(d), s1, a);
1872 M_ILD(GET_LOW_REG(d), s1, a + 4);
1873 store_reg_to_var_int(iptr->dst, d);
1876 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1878 store_reg_to_var_int(iptr->dst, d);
1881 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1883 store_reg_to_var_flt(iptr->dst, d);
1886 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1888 store_reg_to_var_flt(iptr->dst, d);
1893 case ICMD_PUTFIELD: /* ..., value ==> ... */
1894 /* op1 = type, val.i = field offset */
1896 var_to_reg_int(s1, src->prev, REG_ITMP1);
1897 gen_nullptr_check(s1);
1899 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
1900 if (IS_2_WORD_TYPE(iptr->op1)) {
1901 var_to_reg_int(s2, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
1903 var_to_reg_int(s2, src, REG_ITMP2);
1906 var_to_reg_flt(s2, src, REG_FTMP2);
1910 codegen_addpatchref(cd, mcodeptr,
1911 PATCHER_get_putfield,
1912 (unresolved_field *) iptr->target);
1914 if (opt_showdisassemble)
1920 a = ((fieldinfo *) (iptr->val.a))->offset;
1923 switch (iptr->op1) {
1928 M_IST(GET_HIGH_REG(s2), s1, a);
1929 M_IST(GET_LOW_REG(s2), s1, a + 4);
1944 /* branch operations **************************************************/
1946 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1948 a = dseg_addaddress(cd, asm_handle_exception);
1949 M_ALD(REG_ITMP2, REG_PV, a);
1951 var_to_reg_int(s1, src, REG_ITMP1);
1952 M_INTMOVE(s1, REG_ITMP1_XPTR);
1954 if (m->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
1955 M_BL(0); /* get current PC */
1956 M_MFLR(REG_ITMP2_XPC);
1957 if (m->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
1958 M_RTS; /* jump to CTR */
1963 case ICMD_GOTO: /* ... ==> ... */
1964 /* op1 = target JavaVM pc */
1966 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1970 case ICMD_JSR: /* ... ==> ... */
1971 /* op1 = target JavaVM pc */
1973 if (m->isleafmethod) M_MFLR(REG_ITMP2);
1976 M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
1977 if (m->isleafmethod) M_MTLR(REG_ITMP2);
1979 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1982 case ICMD_RET: /* ... ==> ... */
1983 /* op1 = local variable */
1985 var = &(rd->locals[iptr->op1][TYPE_ADR]);
1986 if (var->flags & INMEMORY) {
1987 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
1990 M_MTCTR(var->regoff);
1995 case ICMD_IFNULL: /* ..., value ==> ... */
1996 /* op1 = target JavaVM pc */
1998 var_to_reg_int(s1, src, REG_ITMP1);
2001 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2004 case ICMD_IFNONNULL: /* ..., value ==> ... */
2005 /* op1 = target JavaVM pc */
2007 var_to_reg_int(s1, src, REG_ITMP1);
2010 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2018 case ICMD_IFEQ: /* ..., value ==> ... */
2019 /* op1 = target JavaVM pc, val.i = constant */
2021 var_to_reg_int(s1, src, REG_ITMP1);
2022 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2023 M_CMPI(s1, iptr->val.i);
2026 ICONST(REG_ITMP2, iptr->val.i);
2027 M_CMP(s1, REG_ITMP2);
2050 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2054 case ICMD_IF_LEQ: /* ..., value ==> ... */
2055 /* op1 = target JavaVM pc, val.l = constant */
2057 var_to_reg_int_low(s1, src, REG_ITMP1);
2058 var_to_reg_int_high(s2, src, REG_ITMP2);
2059 if (iptr->val.l == 0) {
2060 M_OR(s1, s2, REG_ITMP3);
2061 M_CMPI(REG_ITMP3, 0);
2063 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2064 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2066 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2069 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2070 M_CMP(s2, REG_ITMP3);
2072 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2073 M_CMP(s1, REG_ITMP3)
2076 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2079 case ICMD_IF_LLT: /* ..., value ==> ... */
2080 /* op1 = target JavaVM pc, val.l = constant */
2081 var_to_reg_int_low(s1, src, REG_ITMP1);
2082 var_to_reg_int_high(s2, src, REG_ITMP2);
2083 /* if (iptr->val.l == 0) { */
2084 /* M_OR(s1, s2, REG_ITMP3); */
2085 /* M_CMPI(REG_ITMP3, 0); */
2088 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2089 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2091 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2093 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2096 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2097 M_CMP(s2, REG_ITMP3);
2099 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2101 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2102 M_CMP(s1, REG_ITMP3)
2105 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2108 case ICMD_IF_LLE: /* ..., value ==> ... */
2109 /* op1 = target JavaVM pc, val.l = constant */
2111 var_to_reg_int_low(s1, src, REG_ITMP1);
2112 var_to_reg_int_high(s2, src, REG_ITMP2);
2113 /* if (iptr->val.l == 0) { */
2114 /* M_OR(s1, s2, REG_ITMP3); */
2115 /* M_CMPI(REG_ITMP3, 0); */
2118 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2119 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2121 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2123 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2126 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2127 M_CMP(s2, REG_ITMP3);
2129 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2131 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2132 M_CMP(s1, REG_ITMP3)
2135 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2138 case ICMD_IF_LNE: /* ..., value ==> ... */
2139 /* op1 = target JavaVM pc, val.l = constant */
2141 var_to_reg_int_low(s1, src, REG_ITMP1);
2142 var_to_reg_int_high(s2, src, REG_ITMP2);
2143 if (iptr->val.l == 0) {
2144 M_OR(s1, s2, REG_ITMP3);
2145 M_CMPI(REG_ITMP3, 0);
2147 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2148 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2150 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2153 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2154 M_CMP(s2, REG_ITMP3);
2156 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2157 M_CMP(s1, REG_ITMP3)
2160 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2163 case ICMD_IF_LGT: /* ..., value ==> ... */
2164 /* op1 = target JavaVM pc, val.l = constant */
2166 var_to_reg_int_low(s1, src, REG_ITMP1);
2167 var_to_reg_int_high(s2, src, REG_ITMP2);
2168 /* if (iptr->val.l == 0) { */
2169 /* M_OR(s1, s2, REG_ITMP3); */
2170 /* M_CMPI(REG_ITMP3, 0); */
2173 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2174 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2176 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2178 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2181 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2182 M_CMP(s2, REG_ITMP3);
2184 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2186 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2187 M_CMP(s1, REG_ITMP3)
2190 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2193 case ICMD_IF_LGE: /* ..., value ==> ... */
2194 /* op1 = target JavaVM pc, val.l = constant */
2195 var_to_reg_int_low(s1, src, REG_ITMP1);
2196 var_to_reg_int_high(s2, src, REG_ITMP2);
2197 /* if (iptr->val.l == 0) { */
2198 /* M_OR(s1, s2, REG_ITMP3); */
2199 /* M_CMPI(REG_ITMP3, 0); */
2202 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2203 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2205 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2207 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2210 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2211 M_CMP(s2, REG_ITMP3);
2213 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2215 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2216 M_CMP(s1, REG_ITMP3)
2219 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2223 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2224 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2225 /******************************************************************
2226 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2227 *******************************************************************/
2228 case ICMD_IF_ACMPEQ:
2230 var_to_reg_int(s1, src->prev, REG_ITMP1);
2231 var_to_reg_int(s2, src, REG_ITMP2);
2234 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2237 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2238 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2239 /******************************************************************
2240 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2241 *******************************************************************/
2242 case ICMD_IF_ACMPNE:
2244 var_to_reg_int(s1, src->prev, REG_ITMP1);
2245 var_to_reg_int(s2, src, REG_ITMP2);
2248 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2251 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2252 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2253 /******************************************************************
2254 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2255 *******************************************************************/
2257 var_to_reg_int(s1, src->prev, REG_ITMP1);
2258 var_to_reg_int(s2, src, REG_ITMP2);
2261 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2264 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2265 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2266 /******************************************************************
2267 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2268 *******************************************************************/
2270 var_to_reg_int(s1, src->prev, REG_ITMP1);
2271 var_to_reg_int(s2, src, REG_ITMP2);
2274 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2277 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2278 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2279 /******************************************************************
2280 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2281 *******************************************************************/
2283 var_to_reg_int(s1, src->prev, REG_ITMP1);
2284 var_to_reg_int(s2, src, REG_ITMP2);
2287 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2290 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2291 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2292 /******************************************************************
2293 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2294 *******************************************************************/
2296 var_to_reg_int(s1, src->prev, REG_ITMP1);
2297 var_to_reg_int(s2, src, REG_ITMP2);
2300 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2303 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2305 var_to_reg_int(s1, src, REG_RESULT);
2306 M_TINTMOVE(src->type, s1, REG_RESULT);
2307 goto nowperformreturn;
2309 var_to_reg_int(s1, src, PACK_REGS(REG_RESULT2, REG_RESULT));
2310 M_TINTMOVE(src->type, s1, PACK_REGS(REG_RESULT2, REG_RESULT));
2311 goto nowperformreturn;
2313 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2315 var_to_reg_flt(s1, src, REG_FRESULT);
2316 M_FLTMOVE(s1, REG_FRESULT);
2317 goto nowperformreturn;
2319 case ICMD_RETURN: /* ... ==> ... */
2325 p = parentargs_base;
2327 /* call trace function */
2331 M_LDA(REG_SP, REG_SP, -10 * 8);
2332 M_DST(REG_FRESULT, REG_SP, 48+0);
2333 M_IST(REG_RESULT, REG_SP, 48+8);
2334 M_AST(REG_ITMP3, REG_SP, 48+12);
2335 M_IST(REG_RESULT2, REG_SP, 48+16);
2337 /* keep this order */
2338 switch (iptr->opc) {
2341 #if defined(__DARWIN__)
2342 M_MOV(REG_RESULT, rd->argintregs[2]);
2343 M_CLR(rd->argintregs[1]);
2345 M_MOV(REG_RESULT, rd->argintregs[3]);
2346 M_CLR(rd->argintregs[2]);
2351 #if defined(__DARWIN__)
2352 M_MOV(REG_RESULT2, rd->argintregs[2]);
2353 M_MOV(REG_RESULT, rd->argintregs[1]);
2355 M_MOV(REG_RESULT2, rd->argintregs[3]);
2356 M_MOV(REG_RESULT, rd->argintregs[2]);
2361 a = dseg_addaddress(cd, m);
2362 M_ALD(rd->argintregs[0], REG_PV, a);
2364 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2365 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2366 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2367 M_ALD(REG_ITMP2, REG_PV, a);
2370 M_DLD(REG_FRESULT, REG_SP, 48+0);
2371 M_ILD(REG_RESULT, REG_SP, 48+8);
2372 M_ALD(REG_ITMP3, REG_SP, 48+12);
2373 M_ILD(REG_RESULT2, REG_SP, 48+16);
2374 M_LDA(REG_SP, REG_SP, 10 * 8);
2378 #if defined(USE_THREADS)
2379 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2380 /* we need to save the proper return value */
2381 switch (iptr->opc) {
2383 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2387 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2390 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2393 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2397 a = dseg_addaddress(cd, BUILTIN_monitorexit);
2398 M_ALD(REG_ITMP3, REG_PV, a);
2400 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 4);
2403 /* and now restore the proper return value */
2404 switch (iptr->opc) {
2406 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2410 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2413 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2416 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2422 /* restore return address */
2424 if (!m->isleafmethod) {
2425 M_ALD(REG_ITMP3, REG_SP, p * 4 + LA_LR_OFFSET);
2429 /* restore saved registers */
2431 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2432 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2434 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2435 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2438 /* deallocate stack */
2440 if (parentargs_base)
2441 M_LDA(REG_SP, REG_SP, parentargs_base * 4);
2449 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2454 tptr = (void **) iptr->target;
2456 s4ptr = iptr->val.a;
2457 l = s4ptr[1]; /* low */
2458 i = s4ptr[2]; /* high */
2460 var_to_reg_int(s1, src, REG_ITMP1);
2462 M_INTMOVE(s1, REG_ITMP1);
2463 } else if (l <= 32768) {
2464 M_LDA(REG_ITMP1, s1, -l);
2466 ICONST(REG_ITMP2, l);
2467 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2473 M_CMPUI(REG_ITMP1, i - 1);
2476 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2477 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2479 /* build jump table top down and use address of lowest entry */
2481 /* s4ptr += 3 + i; */
2485 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2486 dseg_addtarget(cd, (basicblock *) tptr[0]);
2491 /* length of dataseg after last dseg_addtarget is used by load */
2493 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2494 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2495 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2502 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2504 s4 i, l, val, *s4ptr;
2507 tptr = (void **) iptr->target;
2509 s4ptr = iptr->val.a;
2510 l = s4ptr[0]; /* default */
2511 i = s4ptr[1]; /* count */
2513 MCODECHECK((i<<2)+8);
2514 var_to_reg_int(s1, src, REG_ITMP1);
2520 if ((val >= -32768) && (val <= 32767)) {
2524 a = dseg_adds4(cd, val);
2525 M_ILD(REG_ITMP2, REG_PV, a);
2526 M_CMP(s1, REG_ITMP2);
2529 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2530 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2534 /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2536 tptr = (void **) iptr->target;
2537 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2544 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2545 /* op1 = arg count val.a = builtintable entry */
2551 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2552 /* op1 = arg count, val.a = method pointer */
2554 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2555 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2556 case ICMD_INVOKEINTERFACE:
2561 md = lm->parseddesc;
2563 unresolved_method *um = iptr->target;
2564 md = um->methodref->parseddesc.md;
2570 MCODECHECK((s3 << 1) + 64);
2572 /* copy arguments to registers or stack location */
2574 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2575 if (src->varkind == ARGVAR)
2577 if (IS_INT_LNG_TYPE(src->type)) {
2578 if (!md->params[s3].inmemory) {
2579 if (IS_2_WORD_TYPE(src->type))
2581 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2582 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]);
2584 s1 = rd->argintregs[md->params[s3].regoff];
2585 var_to_reg_int(d, src, s1);
2586 M_TINTMOVE(src->type, d, s1);
2588 var_to_reg_int(d, src, PACK_REGS(REG_ITMP3, REG_ITMP1));
2589 M_IST(GET_HIGH_REG(d), REG_SP,
2590 md->params[s3].regoff * 4);
2591 if (IS_2_WORD_TYPE(src->type))
2592 M_IST(GET_LOW_REG(d),
2593 REG_SP, md->params[s3].regoff * 4 + 4);
2597 if (!md->params[s3].inmemory) {
2598 s1 = rd->argfltregs[md->params[s3].regoff];
2599 var_to_reg_flt(d, src, s1);
2602 var_to_reg_flt(d, src, REG_FTMP1);
2603 if (IS_2_WORD_TYPE(src->type))
2604 M_DST(d, REG_SP, md->params[s3].regoff * 4);
2606 M_FST(d, REG_SP, md->params[s3].regoff * 4);
2611 switch (iptr->opc) {
2614 codegen_addpatchref(cd, mcodeptr, bte->fp, iptr->target);
2616 if (opt_showdisassemble)
2622 a = (ptrint) bte->fp;
2625 a = dseg_addaddress(cd, a);
2626 d = md->returntype.type;
2628 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2631 case ICMD_INVOKESPECIAL:
2632 gen_nullptr_check(rd->argintregs[0]);
2633 M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr */
2636 case ICMD_INVOKESTATIC:
2638 unresolved_method *um = iptr->target;
2640 codegen_addpatchref(cd, mcodeptr,
2641 PATCHER_invokestatic_special, um);
2643 if (opt_showdisassemble)
2647 d = md->returntype.type;
2650 a = (ptrint) lm->stubroutine;
2651 d = md->returntype.type;
2654 a = dseg_addaddress(cd, a);
2655 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
2658 case ICMD_INVOKEVIRTUAL:
2659 gen_nullptr_check(rd->argintregs[0]);
2662 unresolved_method *um = iptr->target;
2664 codegen_addpatchref(cd, mcodeptr,
2665 PATCHER_invokevirtual, um);
2667 if (opt_showdisassemble)
2671 d = md->returntype.type;
2674 s1 = OFFSET(vftbl_t, table[0]) +
2675 sizeof(methodptr) * lm->vftblindex;
2676 d = md->returntype.type;
2679 M_ALD(REG_METHODPTR, rd->argintregs[0],
2680 OFFSET(java_objectheader, vftbl));
2681 M_ALD(REG_PV, REG_METHODPTR, s1);
2684 case ICMD_INVOKEINTERFACE:
2685 gen_nullptr_check(rd->argintregs[0]);
2688 unresolved_method *um = iptr->target;
2690 codegen_addpatchref(cd, mcodeptr,
2691 PATCHER_invokeinterface, um);
2693 if (opt_showdisassemble)
2698 d = md->returntype.type;
2701 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2702 sizeof(methodptr*) * lm->class->index;
2704 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2706 d = md->returntype.type;
2709 M_ALD(REG_METHODPTR, rd->argintregs[0],
2710 OFFSET(java_objectheader, vftbl));
2711 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2712 M_ALD(REG_PV, REG_METHODPTR, s2);
2721 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2724 M_LDA(REG_PV, REG_ITMP1, -s1);
2726 s4 ml = -s1, mh = 0;
2727 while (ml < -32768) { ml += 65536; mh--; }
2728 M_LDA(REG_PV, REG_ITMP1, ml);
2729 M_LDAH(REG_PV, REG_PV, mh);
2732 /* d contains return type */
2734 if (d != TYPE_VOID) {
2735 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2736 if (IS_2_WORD_TYPE(iptr->dst->type)) {
2737 s1 = reg_of_var(rd, iptr->dst,
2738 PACK_REGS(REG_RESULT2, REG_RESULT));
2739 M_TINTMOVE(iptr->dst->type,
2740 PACK_REGS(REG_RESULT2, REG_RESULT), s1);
2742 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2743 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2745 store_reg_to_var_int(iptr->dst, s1);
2748 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2749 M_FLTMOVE(REG_FRESULT, s1);
2750 store_reg_to_var_flt(iptr->dst, s1);
2756 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2757 /* val.a: (classinfo*) superclass */
2759 /* superclass is an interface:
2761 * OK if ((sub == NULL) ||
2762 * (sub->vftbl->interfacetablelength > super->index) &&
2763 * (sub->vftbl->interfacetable[-super->index] != NULL));
2765 * superclass is a class:
2767 * OK if ((sub == NULL) || (0
2768 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2769 * super->vftbl->diffvall));
2774 vftbl_t *supervftbl;
2777 super = (classinfo *) iptr->val.a;
2784 superindex = super->index;
2785 supervftbl = super->vftbl;
2788 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2789 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
2791 var_to_reg_int(s1, src, REG_ITMP1);
2793 /* calculate interface checkcast code size */
2797 s2 += (opt_showdisassemble ? 1 : 0);
2799 /* calculate class checkcast code size */
2801 s3 = 8 + (s1 == REG_ITMP1);
2803 s3 += (opt_showdisassemble ? 1 : 0);
2805 /* if class is not resolved, check which code to call */
2809 M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
2811 codegen_addpatchref(cd, mcodeptr,
2812 PATCHER_checkcast_instanceof_flags,
2813 (constant_classref *) iptr->target);
2815 if (opt_showdisassemble)
2818 a = dseg_adds4(cd, 0); /* super->flags */
2819 M_ILD(REG_ITMP2, REG_PV, a);
2820 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2824 /* interface checkcast code */
2826 if (!super || (super->flags & ACC_INTERFACE)) {
2832 codegen_addpatchref(cd, mcodeptr,
2833 PATCHER_checkcast_instanceof_interface,
2834 (constant_classref *) iptr->target);
2836 if (opt_showdisassemble)
2840 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2841 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2842 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2844 codegen_addxcastrefs(cd, mcodeptr);
2845 M_ALD(REG_ITMP3, REG_ITMP2,
2846 OFFSET(vftbl_t, interfacetable[0]) -
2847 superindex * sizeof(methodptr*));
2850 codegen_addxcastrefs(cd, mcodeptr);
2856 /* class checkcast code */
2858 if (!super || !(super->flags & ACC_INTERFACE)) {
2864 codegen_addpatchref(cd, mcodeptr,
2865 PATCHER_checkcast_class,
2866 (constant_classref *) iptr->target);
2868 if (opt_showdisassemble)
2872 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2873 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2874 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
2876 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2877 a = dseg_addaddress(cd, supervftbl);
2878 M_ALD(REG_ITMP2, REG_PV, a);
2879 if (s1 != REG_ITMP1) {
2880 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2881 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2882 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2883 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2885 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2887 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2888 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2889 M_ALD(REG_ITMP2, REG_PV, a);
2890 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2891 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2892 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2895 M_CMPU(REG_ITMP3, REG_ITMP2);
2897 codegen_addxcastrefs(cd, mcodeptr);
2899 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2901 store_reg_to_var_int(iptr->dst, d);
2905 case ICMD_ARRAYCHECKCAST: /* ..., objectref ==> ..., objectref */
2906 /* op1: 1... resolved, 0... not resolved */
2908 var_to_reg_int(s1, src, REG_ITMP1);
2909 M_INTMOVE(s1, rd->argintregs[0]);
2914 codegen_addpatchref(cd, mcodeptr, bte->fp, iptr->target);
2916 if (opt_showdisassemble)
2922 a = (ptrint) bte->fp;
2925 disp = dseg_addaddress(cd, iptr->target);
2926 M_ALD(rd->argintregs[1], REG_PV, disp);
2927 disp = dseg_addaddress(cd, a);
2928 M_ALD(REG_ITMP2, REG_PV, disp);
2933 codegen_addxcastrefs(cd, mcodeptr);
2935 var_to_reg_int(s1, src, REG_ITMP1);
2936 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2938 store_reg_to_var_int(iptr->dst, d);
2942 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2943 /* val.a: (classinfo*) superclass */
2945 /* superclass is an interface:
2947 * return (sub != NULL) &&
2948 * (sub->vftbl->interfacetablelength > super->index) &&
2949 * (sub->vftbl->interfacetable[-super->index] != NULL);
2951 * superclass is a class:
2953 * return ((sub != NULL) && (0
2954 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2955 * super->vftbl->diffvall));
2960 vftbl_t *supervftbl;
2963 super = (classinfo *) iptr->val.a;
2970 superindex = super->index;
2971 supervftbl = super->vftbl;
2974 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2975 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2977 var_to_reg_int(s1, src, REG_ITMP1);
2978 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2980 M_MOV(s1, REG_ITMP1);
2984 /* calculate interface instanceof code size */
2988 s2 += (opt_showdisassemble ? 1 : 0);
2990 /* calculate class instanceof code size */
2994 s3 += (opt_showdisassemble ? 1 : 0);
2998 /* if class is not resolved, check which code to call */
3002 M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
3004 codegen_addpatchref(cd, mcodeptr,
3005 PATCHER_checkcast_instanceof_flags,
3006 (constant_classref *) iptr->target);
3008 if (opt_showdisassemble)
3011 a = dseg_adds4(cd, 0); /* super->flags */
3012 M_ILD(REG_ITMP2, REG_PV, a);
3013 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3017 /* interface instanceof code */
3019 if (!super || (super->flags & ACC_INTERFACE)) {
3025 codegen_addpatchref(cd, mcodeptr,
3026 PATCHER_checkcast_instanceof_interface,
3027 (constant_classref *) iptr->target);
3029 if (opt_showdisassemble)
3033 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3034 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3035 M_LDATST(REG_ITMP2, REG_ITMP2, -superindex);
3037 M_ALD(REG_ITMP1, REG_ITMP1,
3038 OFFSET(vftbl_t, interfacetable[0]) -
3039 superindex * sizeof(methodptr*));
3043 M_IADD_IMM(REG_ZERO, 1, d);
3049 /* class instanceof code */
3051 if (!super || !(super->flags & ACC_INTERFACE)) {
3057 codegen_addpatchref(cd, mcodeptr,
3058 PATCHER_instanceof_class,
3059 (constant_classref *) iptr->target);
3061 if (opt_showdisassemble) {
3066 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3067 a = dseg_addaddress(cd, supervftbl);
3068 M_ALD(REG_ITMP2, REG_PV, a);
3069 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3070 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3072 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3073 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3074 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3075 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3076 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3078 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3079 M_CMPU(REG_ITMP1, REG_ITMP2);
3082 M_IADD_IMM(REG_ZERO, 1, d);
3084 store_reg_to_var_int(iptr->dst, d);
3088 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3090 var_to_reg_int(s1, src, REG_ITMP1);
3093 codegen_addxcheckarefs(cd, mcodeptr);
3096 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3098 M_CMPI(REG_RESULT, 0);
3100 codegen_addxexceptionrefs(cd, mcodeptr);
3103 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3104 /* op1 = dimension, val.a = array descriptor */
3106 /* check for negative sizes and copy sizes to stack if necessary */
3108 MCODECHECK((iptr->op1 << 1) + 64);
3110 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3111 var_to_reg_int(s2, src, REG_ITMP1);
3114 codegen_addxcheckarefs(cd, mcodeptr);
3116 /* copy SAVEDVAR sizes to stack */
3118 if (src->varkind != ARGVAR)
3119 #if defined(__DARWIN__)
3120 M_IST(s2, REG_SP, LA_SIZE + (s1 + INT_ARG_CNT) * 4);
3122 M_IST(s2, REG_SP, LA_SIZE + (s1 + 3) * 4);
3126 /* is patcher function set? */
3129 codegen_addpatchref(cd, mcodeptr,
3130 (functionptr) iptr->target, iptr->val.a);
3132 if (opt_showdisassemble)
3138 a = (ptrint) iptr->val.a;
3141 /* a0 = dimension count */
3143 ICONST(rd->argintregs[0], iptr->op1);
3145 /* a1 = arraydescriptor */
3147 a = dseg_addaddress(cd, iptr->val.a);
3148 M_ALD(rd->argintregs[1], REG_PV, a);
3150 /* a2 = pointer to dimensions = stack pointer */
3152 #if defined(__DARWIN__)
3153 M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + INT_ARG_CNT * 4);
3155 M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + 3 * 4);
3158 a = dseg_addaddress(cd, BUILTIN_multianewarray);
3159 M_ALD(REG_PV, REG_PV, a);
3162 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3165 M_LDA (REG_PV, REG_ITMP1, -s1);
3167 s4 ml = -s1, mh = 0;
3168 while (ml < -32768) {ml += 65536; mh--;}
3169 M_LDA(REG_PV, REG_ITMP1, ml);
3170 M_LDAH(REG_PV, REG_PV, mh);
3172 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3173 M_INTMOVE(REG_RESULT, s1);
3174 store_reg_to_var_int(iptr->dst, s1);
3179 throw_cacao_exception_exit(string_java_lang_InternalError,
3180 "Unknown ICMD %d", iptr->opc);
3183 } /* for instruction */
3185 /* copy values to interface registers */
3187 src = bptr->outstack;
3188 len = bptr->outdepth;
3189 MCODECHECK(64 + len);
3195 if ((src->varkind != STACKVAR)) {
3197 if (IS_FLT_DBL_TYPE(s2)) {
3198 var_to_reg_flt(s1, src, REG_FTMP1);
3199 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3200 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3203 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3207 var_to_reg_int(s1, src, REG_ITMP1);
3208 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3209 M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3212 if (IS_2_WORD_TYPE(s2)) {
3213 M_IST(GET_HIGH_REG(s1),
3214 REG_SP, rd->interfaces[len][s2].regoff * 4);
3215 M_IST(GET_LOW_REG(s1), REG_SP,
3216 rd->interfaces[len][s2].regoff * 4 + 4);
3218 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3226 } /* if (bptr -> flags >= BBREACHED) */
3227 } /* for basic block */
3229 codegen_createlinenumbertable(cd);
3237 /* generate ArithemticException check stubs */
3241 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3242 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3243 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3245 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3249 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3251 (u1 *) mcodeptr - cd->mcodebase);
3255 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3257 if (xcodeptr != NULL) {
3258 disp = xcodeptr - mcodeptr - 1;
3262 xcodeptr = mcodeptr;
3264 if (m->isleafmethod) {
3266 M_AST(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3269 M_MOV(REG_PV, rd->argintregs[0]);
3270 M_MOV(REG_SP, rd->argintregs[1]);
3272 if (m->isleafmethod)
3273 M_MOV(REG_ITMP3, rd->argintregs[2]);
3275 M_ALD(rd->argintregs[2],
3276 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3278 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3280 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3281 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3283 disp = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
3284 M_ALD(REG_ITMP1, REG_PV, disp);
3287 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3289 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3290 M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3292 if (m->isleafmethod) {
3293 M_ALD(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3297 disp = dseg_addaddress(cd, asm_handle_exception);
3298 M_ALD(REG_ITMP3, REG_PV, disp);
3304 /* generate ArrayIndexOutOfBoundsException stubs */
3308 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3309 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3311 (u1 *) mcodeptr - cd->mcodebase);
3315 /* move index register into REG_ITMP1 */
3317 M_MOV(bref->reg, REG_ITMP1);
3319 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3321 if (xcodeptr != NULL) {
3322 disp = xcodeptr - mcodeptr - 1;
3326 xcodeptr = mcodeptr;
3328 if (m->isleafmethod) {
3330 M_AST(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3333 M_MOV(REG_PV, rd->argintregs[0]);
3334 M_MOV(REG_SP, rd->argintregs[1]);
3336 if (m->isleafmethod)
3337 M_MOV(REG_ITMP3, rd->argintregs[2]);
3339 M_ALD(rd->argintregs[2],
3340 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3342 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3343 M_MOV(REG_ITMP1, rd->argintregs[4]);
3345 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 6 * 4));
3346 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 4);
3348 disp = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
3349 M_ALD(REG_ITMP1, REG_PV, disp);
3352 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3354 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 4);
3355 M_IADD_IMM(REG_SP, LA_SIZE + 6 * 4, REG_SP);
3357 if (m->isleafmethod) {
3358 M_ALD(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3362 disp = dseg_addaddress(cd, asm_handle_exception);
3363 M_ALD(REG_ITMP3, REG_PV, disp);
3369 /* generate ArrayStoreException check stubs */
3373 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
3374 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3375 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3377 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3381 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3383 (u1 *) mcodeptr - cd->mcodebase);
3387 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3389 if (xcodeptr != NULL) {
3390 off = xcodeptr - mcodeptr - 1;
3394 xcodeptr = mcodeptr;
3396 M_MOV(REG_PV, rd->argintregs[0]);
3397 M_MOV(REG_SP, rd->argintregs[1]);
3398 M_ALD(rd->argintregs[2],
3399 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3400 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3402 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3403 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3405 disp = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
3406 M_ALD(REG_ITMP1, REG_PV, disp);
3409 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3411 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3412 M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3414 disp = dseg_addaddress(cd, asm_handle_exception);
3415 M_ALD(REG_ITMP3, REG_PV, disp);
3421 /* generate ClassCastException stubs */
3425 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3426 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3427 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3429 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3433 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3435 (u1 *) mcodeptr - cd->mcodebase);
3439 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3441 if (xcodeptr != NULL) {
3442 off = xcodeptr - mcodeptr - 1;
3446 xcodeptr = mcodeptr;
3448 if (m->isleafmethod) {
3450 M_AST(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3453 M_MOV(REG_PV, rd->argintregs[0]);
3454 M_MOV(REG_SP, rd->argintregs[1]);
3456 if (m->isleafmethod)
3457 M_MOV(REG_ITMP3, rd->argintregs[2]);
3459 M_ALD(rd->argintregs[2],
3460 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3462 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3464 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3465 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3467 disp = dseg_addaddress(cd, stacktrace_inline_classcastexception);
3468 M_ALD(REG_ITMP1, REG_PV, disp);
3471 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3473 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3474 M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3476 if (m->isleafmethod) {
3477 M_ALD(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3481 disp = dseg_addaddress(cd, asm_handle_exception);
3482 M_ALD(REG_ITMP3, REG_PV, disp);
3488 /* generate NegativeArraySizeException stubs */
3492 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3493 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3494 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3496 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3500 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3502 (u1 *) mcodeptr - cd->mcodebase);
3506 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3508 if (xcodeptr != NULL) {
3509 off = xcodeptr - mcodeptr - 1;
3513 xcodeptr = mcodeptr;
3515 M_MOV(REG_PV, rd->argintregs[0]);
3516 M_MOV(REG_SP, rd->argintregs[1]);
3517 M_ALD(rd->argintregs[2],
3518 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3519 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3521 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3522 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3524 disp = dseg_addaddress(cd, stacktrace_inline_negativearraysizeexception);
3525 M_ALD(REG_ITMP1, REG_PV, disp);
3528 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3530 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3531 M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3533 disp = dseg_addaddress(cd, asm_handle_exception);
3534 M_ALD(REG_ITMP3, REG_PV, disp);
3540 /* generate NullPointerException stubs */
3544 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3545 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3546 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3548 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3552 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3554 (u1 *) mcodeptr - cd->mcodebase);
3558 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3560 if (xcodeptr != NULL) {
3561 off = xcodeptr - mcodeptr - 1;
3565 xcodeptr = mcodeptr;
3567 if (m->isleafmethod) {
3569 M_AST(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3572 M_MOV(REG_PV, rd->argintregs[0]);
3573 M_MOV(REG_SP, rd->argintregs[1]);
3575 if (m->isleafmethod)
3576 M_MOV(REG_ITMP3, rd->argintregs[2]);
3578 M_ALD(rd->argintregs[2],
3579 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3581 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3583 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3584 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3586 disp = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
3587 M_ALD(REG_ITMP1, REG_PV, disp);
3590 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3592 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3593 M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3595 if (m->isleafmethod) {
3596 M_ALD(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3600 disp = dseg_addaddress(cd, asm_handle_exception);
3601 M_ALD(REG_ITMP3, REG_PV, disp);
3607 /* generate ICMD_CHECKEXCEPTION stubs */
3611 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3612 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3613 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3615 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3619 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3621 (u1 *) mcodeptr - cd->mcodebase);
3625 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3627 if (xcodeptr != NULL) {
3628 off = xcodeptr - mcodeptr - 1;
3632 xcodeptr = mcodeptr;
3634 M_MOV(REG_PV, rd->argintregs[0]);
3635 M_MOV(REG_SP, rd->argintregs[1]);
3636 M_ALD(rd->argintregs[2],
3637 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3638 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3640 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3641 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3643 disp = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
3644 M_ALD(REG_ITMP1, REG_PV, disp);
3647 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3649 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3650 M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3652 disp = dseg_addaddress(cd, asm_handle_exception);
3653 M_ALD(REG_ITMP3, REG_PV, disp);
3659 /* generate patcher stub call code */
3666 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3667 /* check code segment size */
3671 /* Get machine code which is patched back in later. The call is */
3672 /* 1 instruction word long. */
3674 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3677 /* patch in the call to call the following code (done at compile */
3680 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3681 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3683 M_BL(tmpmcodeptr - (xcodeptr + 1));
3685 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3687 /* create stack frame - keep stack 16-byte aligned */
3689 M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
3691 /* move return address onto stack */
3694 M_AST(REG_ITMP3, REG_SP, 4 * 4);
3696 /* move pointer to java_objectheader onto stack */
3698 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3699 /* order reversed because of data segment layout */
3701 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3702 off = dseg_addaddress(cd, NULL); /* vftbl */
3704 if (off >= -32768) {
3705 M_LDA(REG_ITMP3, REG_PV, off);
3707 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3708 M_LDA(REG_ITMP3, REG_ITMP3, off);
3710 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3713 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3716 /* move machine code onto stack */
3718 off = dseg_adds4(cd, mcode);
3719 if (off >= -32768) {
3720 M_ILD(REG_ITMP3, REG_PV, off);
3722 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3723 M_ILD(REG_ITMP3, REG_ITMP3, off);
3725 M_IST(REG_ITMP3, REG_SP, 2 * 4);
3727 /* move class/method/field reference onto stack */
3729 off = dseg_addaddress(cd, pref->ref);
3730 if (off >= -32768) {
3731 M_ALD(REG_ITMP3, REG_PV, off);
3733 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3734 M_ALD(REG_ITMP3, REG_ITMP3, off);
3736 M_AST(REG_ITMP3, REG_SP, 1 * 4);
3738 /* move patcher function pointer onto stack */
3740 off = dseg_addaddress(cd, pref->patcher);
3741 if (off >= -32768) {
3742 M_ALD(REG_ITMP3, REG_PV, off);
3744 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3745 M_ALD(REG_ITMP3, REG_ITMP3, off);
3747 M_AST(REG_ITMP3, REG_SP, 0 * 4);
3749 off = dseg_addaddress(cd, asm_wrapper_patcher);
3750 if (off >= -32768) {
3751 M_ALD(REG_ITMP3, REG_PV, off);
3753 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3754 M_ALD(REG_ITMP3, REG_ITMP3, off);
3763 codegen_finish(m, cd, (ptrint) ((u1 *) mcodeptr - cd->mcodebase));
3765 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3769 /* createcompilerstub **********************************************************
3771 Creates a stub routine which calls the compiler.
3773 *******************************************************************************/
3775 #define COMPSTUBSIZE 6
3777 functionptr createcompilerstub(methodinfo *m)
3779 s4 *s = CNEW(s4, COMPSTUBSIZE); /* memory to hold the stub */
3780 s4 *mcodeptr = s; /* code generation pointer */
3782 M_LDA(REG_ITMP1, REG_PV, 4*4);
3783 M_ALD(REG_PV, REG_PV, 5*4);
3787 s[4] = (s4) m; /* literals to be adressed */
3788 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3790 asm_cacheflush((void *) s, (u1 *) mcodeptr - (u1 *) s);
3792 #if defined(STATISTICS)
3794 count_cstub_len += COMPSTUBSIZE * 4;
3797 return (functionptr) (ptrint) s;
3801 /* createnativestub ************************************************************
3803 Creates a stub routine which calls a native method.
3805 *******************************************************************************/
3807 functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
3808 registerdata *rd, methoddesc *nmd)
3810 s4 *mcodeptr; /* code generation pointer */
3811 s4 stackframesize; /* size of stackframe if needed */
3815 s4 i, j; /* count variables */
3819 /* set some variables */
3822 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3824 /* calculate stackframe size */
3827 sizeof(stackframeinfo) / SIZEOF_VOID_P + /* native stackinfo */
3828 4 + /* 4 stackframeinfo arguments (darwin)*/
3829 nmd->paramcount * 2 + /* assume all are doubles */
3832 stackframesize = (stackframesize + 3) & ~3; /* keep stack 16-byte aligned */
3835 /* create method header */
3837 (void) dseg_addaddress(cd, m); /* MethodPointer */
3838 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
3839 (void) dseg_adds4(cd, 0); /* IsSync */
3840 (void) dseg_adds4(cd, 0); /* IsLeaf */
3841 (void) dseg_adds4(cd, 0); /* IntSave */
3842 (void) dseg_adds4(cd, 0); /* FltSave */
3843 (void) dseg_addlinenumbertablesize(cd);
3844 (void) dseg_adds4(cd, 0); /* ExTableSize */
3847 /* initialize mcode variables */
3849 mcodeptr = (s4 *) cd->mcodebase;
3850 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
3856 M_AST(REG_ITMP1, REG_SP, LA_LR_OFFSET);
3857 M_STWU(REG_SP, REG_SP, -(stackframesize * 4));
3860 /* if function is static, check for initialized */
3862 if ((m->flags & ACC_STATIC) && !m->class->initialized) {
3863 codegen_addpatchref(cd, mcodeptr, PATCHER_clinit, m->class);
3865 if (opt_showdisassemble)
3870 /* parent_argbase == stackframesize * 4 */
3871 mcodeptr = codegen_trace_args(m, cd, rd, mcodeptr, stackframesize * 4 ,
3876 /* save integer and float argument registers */
3878 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
3879 t = md->paramtypes[i].type;
3881 if (IS_INT_LNG_TYPE(t)) {
3882 s1 = md->params[i].regoff;
3883 if (IS_2_WORD_TYPE(t)) {
3884 M_IST(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3885 M_IST(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3887 M_IST(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3892 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3893 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3894 s1 = md->params[i].regoff;
3895 M_DST(rd->argfltregs[s1], REG_SP, LA_SIZE + 4 * 4 + j++ * 8);
3899 /* create native stack info */
3901 M_AADD_IMM(REG_SP, stackframesize * 4 - sizeof(stackframeinfo),
3903 M_MOV(REG_PV, rd->argintregs[1]);
3904 M_AADD_IMM(REG_SP, stackframesize * 4, rd->argintregs[2]);
3905 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 4 + LA_LR_OFFSET);
3906 off = dseg_addaddress(cd, stacktrace_create_native_stackframeinfo);
3907 M_ALD(REG_ITMP1, REG_PV, off);
3911 /* restore integer and float argument registers */
3913 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
3914 t = md->paramtypes[i].type;
3916 if (IS_INT_LNG_TYPE(t)) {
3917 s1 = md->params[i].regoff;
3919 if (IS_2_WORD_TYPE(t)) {
3920 M_ILD(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3921 M_ILD(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3923 M_ILD(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3928 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3929 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3930 s1 = md->params[i].regoff;
3931 M_DLD(rd->argfltregs[i], REG_SP, LA_SIZE + 4 * 4 + j++ * 8);
3936 /* copy or spill arguments to new locations */
3938 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3939 t = md->paramtypes[i].type;
3941 if (IS_INT_LNG_TYPE(t)) {
3942 if (!md->params[i].inmemory) {
3943 if (IS_2_WORD_TYPE(t))
3945 rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
3946 rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
3948 s1 = rd->argintregs[md->params[i].regoff];
3950 if (!nmd->params[j].inmemory) {
3951 if (IS_2_WORD_TYPE(t))
3953 rd->argintregs[GET_LOW_REG(nmd->params[j].regoff)],
3954 rd->argintregs[GET_HIGH_REG(nmd->params[j].regoff)]);
3956 s2 = rd->argintregs[nmd->params[j].regoff];
3957 M_TINTMOVE(t, s1, s2);
3960 s2 = nmd->params[j].regoff;
3961 if (IS_2_WORD_TYPE(t)) {
3962 M_IST(GET_HIGH_REG(s1), REG_SP, s2 * 4);
3963 M_IST(GET_LOW_REG(s1), REG_SP, s2 * 4 + 4);
3965 M_IST(s1, REG_SP, s2 * 4);
3970 s1 = md->params[i].regoff + stackframesize;
3971 s2 = nmd->params[j].regoff;
3973 M_ILD(REG_ITMP1, REG_SP, s1 * 4);
3974 M_IST(REG_ITMP1, REG_SP, s2 * 4);
3975 if (IS_2_WORD_TYPE(t)) {
3976 M_ILD(REG_ITMP1, REG_SP, s1 * 4 + 4);
3977 M_IST(REG_ITMP1, REG_SP, s2 * 4 + 4);
3982 /* We only copy spilled float arguments, as the float argument */
3983 /* registers keep unchanged. */
3985 if (md->params[i].inmemory) {
3986 s1 = md->params[i].regoff + stackframesize;
3987 s2 = nmd->params[j].regoff;
3989 if (IS_2_WORD_TYPE(t)) {
3990 M_DLD(REG_FTMP1, REG_SP, s1 * 4);
3991 M_DST(REG_FTMP1, REG_SP, s2 * 4);
3994 M_FLD(REG_FTMP1, REG_SP, s1 * 4);
3995 M_FST(REG_FTMP1, REG_SP, s2 * 4);
4001 /* put class into second argument register */
4003 if (m->flags & ACC_STATIC) {
4004 off = dseg_addaddress(cd, m->class);
4005 M_ALD(rd->argintregs[1], REG_PV, off);
4008 /* put env into first argument register */
4010 off = dseg_addaddress(cd, &env);
4011 M_ALD(rd->argintregs[0], REG_PV, off);
4013 /* generate the actual native call */
4015 #if !defined(ENABLE_STATICVM)
4017 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m);
4019 if (opt_showdisassemble)
4024 off = dseg_addaddress(cd, f);
4025 M_ALD(REG_PV, REG_PV, off);
4028 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4030 M_LDA(REG_PV, REG_ITMP1, -disp); /* recompute pv from ra */
4033 /* remove native stackframe info */
4035 switch (md->returntype.type) {
4037 M_IST(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);
4041 M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
4044 M_FST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4047 M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4051 M_AADD_IMM(REG_SP, stackframesize * 4 - sizeof(stackframeinfo),
4053 off = dseg_addaddress(cd, stacktrace_remove_stackframeinfo);
4054 M_ALD(REG_ITMP1, REG_PV, off);
4058 switch (md->returntype.type) {
4060 M_ILD(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);
4064 M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
4067 M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4070 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4075 /* print call trace */
4078 M_LDA(REG_SP, REG_SP, -(LA_SIZE + ((1 + 2 + 2 + 1) + 2 + 2) * 4));
4079 M_IST(REG_RESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 0) * 4);
4080 M_IST(REG_RESULT2, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 1) * 4);
4081 M_DST(REG_FRESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2) * 4);
4083 /* keep this order */
4084 switch (m->returntype) {
4087 #if defined(__DARWIN__)
4088 M_MOV(REG_RESULT, rd->argintregs[2]);
4089 M_CLR(rd->argintregs[1]);
4091 M_MOV(REG_RESULT, rd->argintregs[3]);
4092 M_CLR(rd->argintregs[2]);
4097 #if defined(__DARWIN__)
4098 M_MOV(REG_RESULT2, rd->argintregs[2]);
4099 M_MOV(REG_RESULT, rd->argintregs[1]);
4101 M_MOV(REG_RESULT2, rd->argintregs[3]);
4102 M_MOV(REG_RESULT, rd->argintregs[2]);
4107 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
4108 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
4109 off = dseg_addaddress(cd, m);
4110 M_ALD(rd->argintregs[0], REG_PV, off);
4112 off = dseg_addaddress(cd, builtin_displaymethodstop);
4113 M_ALD(REG_ITMP2, REG_PV, off);
4117 M_ILD(REG_RESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 0) * 4);
4118 M_ILD(REG_RESULT2, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 1) * 4);
4119 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2) * 4);
4120 M_LDA(REG_SP, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2 + 2) * 4);
4123 /* check for exception */
4125 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4126 switch (md->returntype.type) {
4128 M_IST(REG_RESULT2, REG_SP, (stackframesize - 1) * 4);
4132 M_IST(REG_RESULT, REG_SP, (stackframesize - 2) * 4);
4135 M_FST(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4138 M_DST(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4142 off = dseg_addaddress(cd, builtin_get_exceptionptrptr);
4143 M_ALD(REG_ITMP1, REG_PV, off);
4146 M_MOV(REG_RESULT, REG_ITMP2);
4148 switch (md->returntype.type) {
4150 M_ILD(REG_RESULT2, REG_SP, (stackframesize - 1) * 4);
4154 M_ILD(REG_RESULT, REG_SP, (stackframesize - 2) * 4);
4157 M_FLD(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4160 M_DLD(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4164 off = dseg_addaddress(cd, &_exceptionptr)
4165 M_ALD(REG_ITMP2, REG_PV, off);
4167 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);/* load exception into reg. itmp1 */
4168 M_TST(REG_ITMP1_XPTR);
4169 M_BNE(4); /* if no exception then return */
4171 M_ALD(REG_ITMP1, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra */
4173 M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe */
4177 /* handle exception */
4180 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
4182 M_ALD(REG_ITMP2, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra */
4185 M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe */
4187 M_IADD_IMM(REG_ITMP2, -4, REG_ITMP2_XPC); /* fault address */
4189 off = dseg_addaddress(cd, asm_handle_nat_exception);
4190 M_ALD(REG_ITMP3, REG_PV, off);
4194 /* generate patcher stub call code */
4202 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4203 /* Get machine code which is patched back in later. The call is */
4204 /* 1 instruction word long. */
4206 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4207 mcode = (u4) *xcodeptr;
4209 /* patch in the call to call the following code (done at compile */
4212 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4213 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4215 M_BL(tmpmcodeptr - (xcodeptr + 1));
4217 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4219 /* create stack frame - keep stack 16-byte aligned */
4221 M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
4223 /* move return address onto stack */
4226 M_AST(REG_ITMP3, REG_SP, 4 * 4);
4228 /* move pointer to java_objectheader onto stack */
4230 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4231 /* order reversed because of data segment layout */
4233 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4234 off = dseg_addaddress(cd, NULL); /* vftbl */
4236 M_LDA(REG_ITMP3, REG_PV, off);
4237 M_AST(REG_ITMP3, REG_SP, 3 * 4);
4240 M_AST(REG_ITMP3, REG_SP, 3 * 4);
4243 /* move machine code onto stack */
4245 off = dseg_adds4(cd, mcode);
4246 M_ILD(REG_ITMP3, REG_PV, off);
4247 M_IST(REG_ITMP3, REG_SP, 2 * 4);
4249 /* move class/method/field reference onto stack */
4251 off = dseg_addaddress(cd, pref->ref);
4252 M_ALD(REG_ITMP3, REG_PV, off);
4253 M_AST(REG_ITMP3, REG_SP, 1 * 4);
4255 /* move patcher function pointer onto stack */
4257 off = dseg_addaddress(cd, pref->patcher);
4258 M_ALD(REG_ITMP3, REG_PV, off);
4259 M_AST(REG_ITMP3, REG_SP, 0 * 4);
4261 off = dseg_addaddress(cd, asm_wrapper_patcher);
4262 M_ALD(REG_ITMP3, REG_PV, off);
4268 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4270 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4272 return m->entrypoint;
4276 s4 *codegen_trace_args(methodinfo *m, codegendata *cd, registerdata *rd,
4277 s4 *mcodeptr, s4 parentargs_base, bool nativestub)
4288 /* Build up Stackframe for builtin_trace_args call (a multiple of 16) */
4290 /* LA + TRACE_ARGS_NUM u8 args + methodinfo + LR */
4291 /* LA_SIZE(=6*4) + 8*8 + 4 + 4 + 0(Padding) */
4292 /* 6 * 4 + 8 * 8 + 2 * 4 = 12 * 8 = 6 * 16 */
4294 /* LA + (TRACE_ARGS_NUM - INT_ARG_CNT/2) u8 args + methodinfo */
4295 /* + INT_ARG_CNT * 4 ( save integer registers) + LR + 8 + 8 (Padding) */
4296 /* LA_SIZE(=2*4) + 4 * 8 + 4 + 8 * 4 + 4 + 8 */
4297 /* 2 * 4 + 4 * 8 + 10 * 4 + 1 * 8 + 8= 12 * 8 = 6 * 16 */
4299 /* in nativestubs no Place to save the LR (Link Register) would be needed */
4300 /* but since the stack frame has to be aligned the 4 Bytes would have to */
4301 /* be padded again */
4303 #if defined(__DARWIN__)
4304 stack_size = LA_SIZE + (TRACE_ARGS_NUM + 1) * 8;
4306 stack_size = 6 * 16;
4308 M_LDA(REG_SP, REG_SP, -stack_size);
4312 M_IST(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
4314 M_CLR(REG_ITMP1); /* clear help register */
4316 /* save up to TRACE_ARGS_NUM arguments into the reserved stack space */
4317 #if defined(__DARWIN__)
4318 /* Copy Params starting from first to Stack */
4319 /* since TRACE_ARGS == INT_ARG_CNT all used integer argument regs */
4323 /* Copy Params starting from fifth to Stack (INT_ARG_CNT/2) are in */
4324 /* integer argument regs */
4325 /* all integer argument registers have to be saved */
4326 for (p = 0; p < 8; p++) {
4327 d = rd->argintregs[p];
4328 /* save integer argument registers */
4329 M_IST(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
4333 stack_off = LA_SIZE;
4334 for (; p < md->paramcount && p < TRACE_ARGS_NUM; p++, stack_off += 8) {
4335 t = md->paramtypes[p].type;
4336 if (IS_INT_LNG_TYPE(t)) {
4337 if (!md->params[p].inmemory) { /* Param in Arg Reg */
4338 if (IS_2_WORD_TYPE(t)) {
4339 M_IST(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
4340 , REG_SP, stack_off);
4341 M_IST(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
4342 , REG_SP, stack_off + 4);
4344 M_IST(REG_ITMP1, REG_SP, stack_off);
4345 M_IST(rd->argintregs[md->params[p].regoff]
4346 , REG_SP, stack_off + 4);
4348 } else { /* Param on Stack */
4349 s1 = (md->params[p].regoff + parentargs_base) * 4
4351 if (IS_2_WORD_TYPE(t)) {
4352 M_ILD(REG_ITMP2, REG_SP, s1);
4353 M_IST(REG_ITMP2, REG_SP, stack_off);
4354 M_ILD(REG_ITMP2, REG_SP, s1 + 4);
4355 M_IST(REG_ITMP2, REG_SP, stack_off + 4);
4357 M_IST(REG_ITMP1, REG_SP, stack_off);
4358 M_ILD(REG_ITMP2, REG_SP, s1);
4359 M_IST(REG_ITMP2, REG_SP, stack_off + 4);
4362 } else { /* IS_FLT_DBL_TYPE(t) */
4363 if (!md->params[p].inmemory) { /* in Arg Reg */
4364 s1 = rd->argfltregs[md->params[p].regoff];
4365 if (!IS_2_WORD_TYPE(t)) {
4366 M_IST(REG_ITMP1, REG_SP, stack_off);
4367 M_FST(s1, REG_SP, stack_off + 4);
4369 M_DST(s1, REG_SP, stack_off);
4371 } else { /* on Stack */
4372 /* this should not happen */
4377 /* load first 4 (==INT_ARG_CNT/2) arguments into integer registers */
4378 #if defined(__DARWIN__)
4379 for (p = 0; p < 8; p++) {
4380 d = rd->argintregs[p];
4381 M_ILD(d, REG_SP, LA_SIZE + p * 4);
4385 /* Set integer and float argument registers vor trace_args call */
4386 /* offset to saved integer argument registers */
4387 stack_off = LA_SIZE + 4 * 8 + 4;
4388 for (p = 0; (p < 4) && (p < md->paramcount); p++) {
4389 t = md->paramtypes[p].type;
4390 if (IS_INT_LNG_TYPE(t)) {
4391 /* "stretch" int types */
4392 if (!IS_2_WORD_TYPE(t)) {
4393 M_CLR(rd->argintregs[2 * p]);
4394 M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off);
4397 M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off + 4);
4398 M_ILD(rd->argintregs[2 * p], REG_SP,stack_off);
4401 } else { /* Float/Dbl */
4402 if (!md->params[p].inmemory) { /* Param in Arg Reg */
4403 /* use reserved Place on Stack (sp + 5 * 16) to copy */
4404 /* float/double arg reg to int reg */
4405 s1 = rd->argfltregs[md->params[p].regoff];
4406 if (!IS_2_WORD_TYPE(t)) {
4407 M_FST(s1, REG_SP, 5 * 16);
4408 M_ILD(rd->argintregs[2 * p + 1], REG_SP, 5 * 16);
4409 M_CLR(rd->argintregs[2 * p]);
4411 M_DST(s1, REG_SP, 5 * 16);
4412 M_ILD(rd->argintregs[2 * p + 1], REG_SP, 5 * 16 + 4);
4413 M_ILD(rd->argintregs[2 * p], REG_SP, 5 * 16);
4420 /* put methodinfo pointer on Stackframe */
4421 p = dseg_addaddress(cd, m);
4422 M_ALD(REG_ITMP1, REG_PV, p);
4423 #if defined(__DARWIN__)
4424 M_AST(REG_ITMP1, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8);
4426 M_AST(REG_ITMP1, REG_SP, LA_SIZE + 4 * 8);
4428 p = dseg_addaddress(cd, (void *) builtin_trace_args);
4429 M_ALD(REG_ITMP2, REG_PV, p);
4433 #if defined(__DARWIN__)
4434 /* restore integer argument registers from the reserved stack space */
4436 stack_off = LA_SIZE;
4437 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM;
4438 p++, stack_off += 8) {
4439 t = md->paramtypes[p].type;
4441 if (IS_INT_LNG_TYPE(t)) {
4442 if (!md->params[p].inmemory) {
4443 if (IS_2_WORD_TYPE(t)) {
4444 M_ILD(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
4445 , REG_SP, stack_off);
4446 M_ILD(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
4447 , REG_SP, stack_off + 4);
4449 M_ILD(rd->argintregs[md->params[p].regoff]
4450 , REG_SP, stack_off + 4);
4457 for (p = 0; p < 8; p++) {
4458 d = rd->argintregs[p];
4459 /* save integer argument registers */
4460 M_ILD(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
4465 M_ILD(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
4467 M_LDA(REG_SP, REG_SP, stack_size);
4474 * These are local overrides for various environment variables in Emacs.
4475 * Please do not remove this and leave it at the end of the file, where
4476 * Emacs will automagically detect them.
4477 * ---------------------------------------------------------------------
4480 * indent-tabs-mode: t