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 3037 2005-07-13 16:12:20Z 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;
109 /* prevent compiler warnings */
122 /* space to save used callee saved registers */
124 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
125 savedregs_num += 2 * (FLT_SAV_CNT - rd->savfltreguse);
127 parentargs_base = rd->memuse + savedregs_num;
129 #if defined(USE_THREADS)
130 /* space to save argument of monitor_enter and Return Values to survive */
131 /* monitor_exit. The stack position for the argument can not be shared */
132 /* with place to save the return register on PPC, since both values */
134 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
135 /* reserve 2 slots for long/double return values for monitorexit */
137 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
138 parentargs_base += 3;
140 parentargs_base += 2;
145 /* create method header */
147 parentargs_base = (parentargs_base + 3) & ~3;
149 (void) dseg_addaddress(cd, m); /* MethodPointer */
150 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
152 #if defined(USE_THREADS)
153 /* IsSync contains the offset relative to the stack pointer for the
154 argument of monitor_exit used in the exception handler. Since the
155 offset could be zero and give a wrong meaning of the flag it is
159 if (checksync && (m->flags & ACC_SYNCHRONIZED))
160 (void) dseg_adds4(cd, (rd->memuse + 1) * 4); /* IsSync */
163 (void) dseg_adds4(cd, 0); /* IsSync */
165 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
166 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
167 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
169 dseg_addlinenumbertablesize(cd);
171 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
173 /* create exception table */
175 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
176 dseg_addtarget(cd, ex->start);
177 dseg_addtarget(cd, ex->end);
178 dseg_addtarget(cd, ex->handler);
179 (void) dseg_addaddress(cd, ex->catchtype.cls);
182 /* initialize mcode variables */
184 mcodeptr = (s4 *) cd->mcodebase;
185 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
186 MCODECHECK(128 + m->paramcount);
188 /* create stack frame (if necessary) */
190 if (!m->isleafmethod) {
192 M_AST(REG_ITMP3, REG_SP, LA_LR_OFFSET);
195 if (parentargs_base) {
196 M_STWU(REG_SP, REG_SP, -parentargs_base * 4);
199 /* save return address and used callee saved registers */
202 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
203 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
205 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
206 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
209 /* take arguments out of register or stack frame */
213 for (p = 0, l = 0; p < md->paramcount; p++) {
214 t = md->paramtypes[p].type;
215 var = &(rd->locals[l][t]);
217 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
221 s1 = md->params[p].regoff;
222 if (IS_INT_LNG_TYPE(t)) { /* integer args */
223 if (IS_2_WORD_TYPE(t))
224 s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
225 rd->argintregs[GET_HIGH_REG(s1)]);
227 s2 = rd->argintregs[s1];
228 if (!md->params[p].inmemory) { /* register arguments */
229 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
230 M_TINTMOVE(t, s2, var->regoff);
232 } else { /* reg arg -> spilled */
233 if (IS_2_WORD_TYPE(t)) {
234 M_IST(GET_HIGH_REG(s2), REG_SP, var->regoff * 4);
235 M_IST(GET_LOW_REG(s2), REG_SP, var->regoff * 4 + 4);
237 M_IST(s2, REG_SP, var->regoff * 4);
241 } else { /* stack arguments */
242 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
243 if (IS_2_WORD_TYPE(t)) {
244 M_ILD(GET_HIGH_REG(var->regoff), REG_SP,
245 (parentargs_base + s1) * 4);
246 M_ILD(GET_LOW_REG(var->regoff), REG_SP,
247 (parentargs_base + s1) * 4 + 4);
249 M_ILD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
252 } else { /* stack arg -> spilled */
254 M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4);
255 M_IST(REG_ITMP1, REG_SP, var->regoff * 4);
256 if (IS_2_WORD_TYPE(t)) {
257 M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4 +4);
258 M_IST(REG_ITMP1, REG_SP, var->regoff * 4 + 4);
261 /* Reuse Memory Position on Caller Stack */
262 var->regoff = parentargs_base + s1;
267 } else { /* floating args */
268 if (!md->params[p].inmemory) { /* register arguments */
269 s2 = rd->argfltregs[s1];
270 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
271 M_FLTMOVE(s2, var->regoff);
273 } else { /* reg arg -> spilled */
274 if (IS_2_WORD_TYPE(t))
275 M_DST(s2, REG_SP, var->regoff * 4);
277 M_FST(s2, REG_SP, var->regoff * 4);
280 } else { /* stack arguments */
281 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
282 if (IS_2_WORD_TYPE(t))
283 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
286 M_FLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
288 } else { /* stack-arg -> spilled */
290 if (IS_2_WORD_TYPE(t)) {
291 M_DLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
292 M_DST(REG_FTMP1, REG_SP, var->regoff * 4);
293 var->regoff = parentargs_base + s1;
296 M_FLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
297 M_FST(REG_FTMP1, REG_SP, var->regoff * 4);
300 /* Reuse Memory Position on Caller Stack */
301 var->regoff = parentargs_base + s1;
308 /* save monitorenter argument */
310 #if defined(USE_THREADS)
311 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
312 /* stack offset for monitor argument */
318 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT * 4 + FLT_ARG_CNT * 8));
320 for (p = 0; p < INT_ARG_CNT; p++)
321 M_IST(rd->argintregs[p], REG_SP, p * 4);
323 for (p = 0; p < FLT_ARG_CNT * 2; p += 2)
324 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
326 s1 += INT_ARG_CNT + FLT_ARG_CNT;
330 /* decide which monitor enter function to call */
332 if (m->flags & ACC_STATIC) {
333 p = dseg_addaddress(cd, m->class);
334 M_ALD(REG_ITMP1, REG_PV, p);
335 M_AST(REG_ITMP1, REG_SP, s1 * 4);
336 M_MOV(REG_ITMP1, rd->argintregs[0]);
337 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
338 M_ALD(REG_ITMP3, REG_PV, p);
343 M_TST(rd->argintregs[0]);
345 codegen_addxnullrefs(cd, mcodeptr);
346 M_AST(rd->argintregs[0], REG_SP, s1 * 4);
347 p = dseg_addaddress(cd, BUILTIN_monitorenter);
348 M_ALD(REG_ITMP3, REG_PV, p);
355 for (p = 0; p < INT_ARG_CNT; p++)
356 M_ILD(rd->argintregs[p], REG_SP, p * 4);
358 for (p = 0; p < FLT_ARG_CNT; p++)
359 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
362 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
368 /* call trace function */
371 mcodeptr = codegen_trace_args(m, cd, rd, mcodeptr, parentargs_base, false);
373 } /* if (runverbose) */
376 /* end of header generation */
378 /* walk through all basic blocks */
379 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
381 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
383 if (bptr->flags >= BBREACHED) {
385 /* branch resolving */
389 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
390 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
396 /* copy interface registers to their destination */
404 while (src != NULL) {
406 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
407 /* d = reg_of_var(m, src, REG_ITMP1); */
408 if (!(src->flags & INMEMORY))
412 M_INTMOVE(REG_ITMP1, d);
413 store_reg_to_var_int(src, d);
419 while (src != NULL) {
421 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
422 d = reg_of_var(rd, src, REG_ITMP1);
423 M_INTMOVE(REG_ITMP1, d);
424 store_reg_to_var_int(src, d);
426 if (src->type == TYPE_LNG)
427 d = reg_of_var(rd, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
429 d = reg_of_var(rd, src, REG_IFTMP);
430 if ((src->varkind != STACKVAR)) {
432 if (IS_FLT_DBL_TYPE(s2)) {
433 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
434 s1 = rd->interfaces[len][s2].regoff;
437 if (IS_2_WORD_TYPE(s2)) {
439 4 * rd->interfaces[len][s2].regoff);
442 4 * rd->interfaces[len][s2].regoff);
445 store_reg_to_var_flt(src, d);
447 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
448 s1 = rd->interfaces[len][s2].regoff;
451 if (IS_2_WORD_TYPE(s2)) {
452 M_ILD(GET_HIGH_REG(d), REG_SP,
453 4 * rd->interfaces[len][s2].regoff);
454 M_ILD(GET_LOW_REG(d), REG_SP,
455 4 * rd->interfaces[len][s2].regoff + 4);
458 4 * rd->interfaces[len][s2].regoff);
461 store_reg_to_var_int(src, d);
471 /* walk through all instructions */
476 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
477 if (iptr->line != currentline) {
478 dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
479 currentline = iptr->line;
482 MCODECHECK(64); /* an instruction usually needs < 64 words */
485 case ICMD_NOP: /* ... ==> ... */
486 case ICMD_INLINE_START:
487 case ICMD_INLINE_END:
490 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
492 var_to_reg_int(s1, src, REG_ITMP1);
495 codegen_addxnullrefs(cd, mcodeptr);
498 /* constant operations ************************************************/
500 case ICMD_ICONST: /* ... ==> ..., constant */
501 /* op1 = 0, val.i = constant */
503 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
504 ICONST(d, iptr->val.i);
505 store_reg_to_var_int(iptr->dst, d);
508 case ICMD_LCONST: /* ... ==> ..., constant */
509 /* op1 = 0, val.l = constant */
511 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
512 LCONST(d, iptr->val.l);
513 store_reg_to_var_int(iptr->dst, d);
516 case ICMD_FCONST: /* ... ==> ..., constant */
517 /* op1 = 0, val.f = constant */
519 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
520 a = dseg_addfloat(cd, iptr->val.f);
522 store_reg_to_var_flt(iptr->dst, d);
525 case ICMD_DCONST: /* ... ==> ..., constant */
526 /* op1 = 0, val.d = constant */
528 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
529 a = dseg_adddouble(cd, iptr->val.d);
531 store_reg_to_var_flt(iptr->dst, d);
534 case ICMD_ACONST: /* ... ==> ..., constant */
535 /* op1 = 0, val.a = constant */
537 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
538 ICONST(d, (u4) iptr->val.a);
539 store_reg_to_var_int(iptr->dst, d);
543 /* load/store operations **********************************************/
545 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
546 case ICMD_LLOAD: /* op1 = local variable */
549 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
550 if (IS_2_WORD_TYPE(var->type)) /* TYPE_LNG */
551 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
553 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
554 if ((iptr->dst->varkind == LOCALVAR) &&
555 (iptr->dst->varnum == iptr->op1))
558 if (var->flags & INMEMORY) {
559 if (IS_2_WORD_TYPE(var->type)) {
560 M_ILD(GET_HIGH_REG(d), REG_SP, var->regoff * 4);
561 M_ILD(GET_LOW_REG(d), REG_SP, var->regoff * 4 + 4);
563 M_ILD(d, REG_SP, var->regoff * 4);
566 M_TINTMOVE(var->type, var->regoff, d);
568 store_reg_to_var_int(iptr->dst, d);
571 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
572 case ICMD_DLOAD: /* op1 = local variable */
574 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
575 if ((iptr->dst->varkind == LOCALVAR) &&
576 (iptr->dst->varnum == iptr->op1))
578 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
579 if (var->flags & INMEMORY)
580 if (IS_2_WORD_TYPE(var->type))
581 M_DLD(d, REG_SP, 4 * var->regoff);
583 M_FLD(d, REG_SP, 4 * var->regoff);
585 M_FLTMOVE(var->regoff, d);
587 store_reg_to_var_flt(iptr->dst, d);
591 case ICMD_ISTORE: /* ..., value ==> ... */
592 case ICMD_LSTORE: /* op1 = local variable */
595 if ((src->varkind == LOCALVAR) &&
596 (src->varnum == iptr->op1))
598 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
599 if (var->flags & INMEMORY) {
600 if (IS_2_WORD_TYPE(var->type)) {
601 var_to_reg_int(s1, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
602 M_IST(GET_HIGH_REG(s1), REG_SP, var->regoff * 4);
603 M_IST(GET_LOW_REG(s1), REG_SP, var->regoff * 4 + 4);
605 var_to_reg_int(s1, src, REG_ITMP1);
606 M_IST(s1, REG_SP, var->regoff * 4);
610 var_to_reg_int(s1, src, var->regoff);
611 M_TINTMOVE(var->type, s1, var->regoff);
615 case ICMD_FSTORE: /* ..., value ==> ... */
616 case ICMD_DSTORE: /* op1 = local variable */
618 if ((src->varkind == LOCALVAR) &&
619 (src->varnum == iptr->op1))
621 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
622 if (var->flags & INMEMORY) {
623 var_to_reg_flt(s1, src, REG_FTMP1);
624 if (var->type == TYPE_DBL)
625 M_DST(s1, REG_SP, 4 * var->regoff);
627 M_FST(s1, REG_SP, 4 * var->regoff);
629 var_to_reg_flt(s1, src, var->regoff);
630 M_FLTMOVE(s1, var->regoff);
635 /* pop/dup/swap operations ********************************************/
637 /* attention: double and longs are only one entry in CACAO ICMDs */
639 case ICMD_POP: /* ..., value ==> ... */
640 case ICMD_POP2: /* ..., value, value ==> ... */
643 case ICMD_DUP: /* ..., a ==> ..., a, a */
644 M_COPY(src, iptr->dst);
647 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
649 M_COPY(src, iptr->dst);
650 M_COPY(src->prev, iptr->dst->prev);
651 M_COPY(iptr->dst, iptr->dst->prev->prev);
654 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
656 M_COPY(src, iptr->dst);
657 M_COPY(src->prev, iptr->dst->prev);
658 M_COPY(src->prev->prev, iptr->dst->prev->prev);
659 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
662 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
664 M_COPY(src, iptr->dst);
665 M_COPY(src->prev, iptr->dst->prev);
668 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
670 M_COPY(src, iptr->dst);
671 M_COPY(src->prev, iptr->dst->prev);
672 M_COPY(src->prev->prev, iptr->dst->prev->prev);
673 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
674 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
677 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
679 M_COPY(src, iptr->dst);
680 M_COPY(src->prev, iptr->dst->prev);
681 M_COPY(src->prev->prev, iptr->dst->prev->prev);
682 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
683 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
684 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
687 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
689 M_COPY(src, iptr->dst->prev);
690 M_COPY(src->prev, iptr->dst);
694 /* integer operations *************************************************/
696 case ICMD_INEG: /* ..., value ==> ..., - value */
698 var_to_reg_int(s1, src, REG_ITMP1);
699 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
701 store_reg_to_var_int(iptr->dst, d);
704 case ICMD_LNEG: /* ..., value ==> ..., - value */
706 var_to_reg_int(s1, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
707 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
708 M_SUBFIC(GET_LOW_REG(s1), 0, GET_LOW_REG(d));
709 M_SUBFZE(GET_HIGH_REG(s1), GET_HIGH_REG(d));
710 store_reg_to_var_int(iptr->dst, d);
713 case ICMD_I2L: /* ..., value ==> ..., value */
715 var_to_reg_int(s1, src, REG_ITMP2);
716 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
717 M_INTMOVE(s1, GET_LOW_REG(d));
718 M_SRA_IMM(GET_LOW_REG(d), 31, GET_HIGH_REG(d));
719 store_reg_to_var_int(iptr->dst, d);
722 case ICMD_L2I: /* ..., value ==> ..., value */
724 var_to_reg_int_low(s1, src, REG_ITMP2);
725 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
727 store_reg_to_var_int(iptr->dst, d);
730 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
732 var_to_reg_int(s1, src, REG_ITMP1);
733 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
735 store_reg_to_var_int(iptr->dst, d);
738 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
740 var_to_reg_int(s1, src, REG_ITMP1);
741 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
743 store_reg_to_var_int(iptr->dst, d);
746 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
748 var_to_reg_int(s1, src, REG_ITMP1);
749 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
751 store_reg_to_var_int(iptr->dst, d);
755 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
757 var_to_reg_int(s1, src->prev, REG_ITMP1);
758 var_to_reg_int(s2, src, REG_ITMP2);
759 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
761 store_reg_to_var_int(iptr->dst, d);
764 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
765 /* val.i = constant */
767 var_to_reg_int(s1, src, REG_ITMP1);
768 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
769 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
770 M_IADD_IMM(s1, iptr->val.i, d);
772 ICONST(REG_ITMP2, iptr->val.i);
773 M_IADD(s1, REG_ITMP2, d);
775 store_reg_to_var_int(iptr->dst, d);
778 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
780 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
781 var_to_reg_int_low(s2, src, REG_ITMP2);
782 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
783 M_ADDC(s1, s2, GET_LOW_REG(d));
784 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
785 var_to_reg_int_high(s2, src, REG_ITMP3);
786 M_ADDE(s1, s2, GET_HIGH_REG(d));
787 store_reg_to_var_int(iptr->dst, d);
790 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
791 /* val.l = constant */
793 s3 = iptr->val.l & 0xffffffff;
794 var_to_reg_int_low(s1, src, REG_ITMP1);
795 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
796 if ((s3 >= -32768) && (s3 <= 32767)) {
797 M_ADDIC(s1, s3, GET_LOW_REG(d));
800 ICONST(REG_ITMP2, s3);
801 M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
804 var_to_reg_int_high(s1, src, REG_ITMP1);
805 s3 = iptr->val.l >> 32;
807 M_ADDME(s1, GET_HIGH_REG(d));
809 M_ADDZE(s1, GET_HIGH_REG(d));
811 ICONST(REG_ITMP3, s3);
812 M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
814 store_reg_to_var_int(iptr->dst, d);
817 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
819 var_to_reg_int(s1, src->prev, REG_ITMP1);
820 var_to_reg_int(s2, src, REG_ITMP2);
821 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
823 store_reg_to_var_int(iptr->dst, d);
826 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
827 /* val.i = constant */
829 var_to_reg_int(s1, src, REG_ITMP1);
830 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
831 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
832 M_IADD_IMM(s1, -iptr->val.i, d);
834 ICONST(REG_ITMP2, -iptr->val.i);
835 M_IADD(s1, REG_ITMP2, d);
837 store_reg_to_var_int(iptr->dst, d);
840 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
842 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
843 var_to_reg_int_low(s2, src, REG_ITMP2);
844 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
845 M_SUBC(s1, s2, GET_LOW_REG(d));
846 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
847 var_to_reg_int_high(s2, src, REG_ITMP3);
848 M_SUBE(s1, s2, GET_HIGH_REG(d));
849 store_reg_to_var_int(iptr->dst, d);
852 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
853 /* val.l = constant */
855 s3 = (-iptr->val.l) & 0xffffffff;
856 var_to_reg_int_low(s1, src, REG_ITMP1);
857 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
858 if ((s3 >= -32768) && (s3 <= 32767)) {
859 M_ADDIC(s1, s3, GET_LOW_REG(d));
861 ICONST(REG_ITMP2, s3);
862 M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
864 var_to_reg_int_high(s1, src, REG_ITMP1);
865 s3 = (-iptr->val.l) >> 32;
867 M_ADDME(s1, GET_HIGH_REG(d));
869 M_ADDZE(s1, GET_HIGH_REG(d));
871 ICONST(REG_ITMP3, s3);
872 M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
874 store_reg_to_var_int(iptr->dst, d);
877 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
879 var_to_reg_int(s1, src->prev, REG_ITMP1);
880 var_to_reg_int(s2, src, REG_ITMP2);
883 codegen_addxdivrefs(cd, mcodeptr);
884 M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
885 M_CMP(REG_ITMP3, s1);
886 d = reg_of_var(rd, iptr->dst, REG_ITMP3); /* does not change flags*/
887 M_BNE(3 + (s1 != d));
889 M_BNE(1 + (s1 != d));
893 store_reg_to_var_int(iptr->dst, d);
896 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
898 var_to_reg_int(s1, src->prev, REG_ITMP1);
899 var_to_reg_int(s2, src, REG_ITMP2);
902 codegen_addxdivrefs(cd, mcodeptr);
903 M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
904 M_CMP(REG_ITMP3, s1);
905 d = reg_of_var(rd, iptr->dst, REG_ITMP3); /* does not change flags*/
911 M_IDIV(s1, s2, REG_ITMP3);
912 M_IMUL(REG_ITMP3, s2, REG_ITMP3);
913 M_ISUB(s1, REG_ITMP3, d);
914 store_reg_to_var_int(iptr->dst, d);
917 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
918 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
923 var_to_reg_int(s2, src, PACK_REGS(REG_ITMP1, REG_ITMP2));
924 M_OR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
926 codegen_addxdivrefs(cd, mcodeptr);
928 s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[1].regoff)],
929 rd->argintregs[GET_HIGH_REG(md->params[1].regoff)]);
930 M_TINTMOVE(TYPE_LNG, s2, s3);
932 var_to_reg_int(s1, src->prev, PACK_REGS(REG_ITMP1, REG_ITMP2));
933 s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[0].regoff)],
934 rd->argintregs[GET_HIGH_REG(md->params[0].regoff)]);
935 M_TINTMOVE(TYPE_LNG, s1, s3);
937 disp = dseg_addaddress(cd, bte->fp);
938 M_ALD(REG_ITMP1, REG_PV, disp);
942 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_RESULT2, REG_RESULT));
943 M_TINTMOVE(TYPE_LNG, PACK_REGS(REG_RESULT2, REG_RESULT), d);
944 store_reg_to_var_int(iptr->dst, d);
947 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
949 var_to_reg_int(s1, src->prev, REG_ITMP1);
950 var_to_reg_int(s2, src, REG_ITMP2);
951 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
953 store_reg_to_var_int(iptr->dst, d);
956 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
957 /* val.i = constant */
959 var_to_reg_int(s1, src, REG_ITMP1);
960 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
961 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
962 M_IMUL_IMM(s1, iptr->val.i, d);
965 ICONST(REG_ITMP2, iptr->val.i);
966 M_IMUL(s1, REG_ITMP2, d);
968 store_reg_to_var_int(iptr->dst, d);
971 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
973 var_to_reg_int(s1, src, REG_ITMP1);
974 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
975 M_SRA_IMM(s1, iptr->val.i, d);
977 store_reg_to_var_int(iptr->dst, d);
980 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
982 var_to_reg_int(s1, src->prev, REG_ITMP1);
983 var_to_reg_int(s2, src, REG_ITMP2);
984 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
985 M_AND_IMM(s2, 0x1f, REG_ITMP3);
986 M_SLL(s1, REG_ITMP3, d);
987 store_reg_to_var_int(iptr->dst, d);
990 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
991 /* val.i = constant */
993 var_to_reg_int(s1, src, REG_ITMP1);
994 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
995 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
996 store_reg_to_var_int(iptr->dst, d);
999 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1001 var_to_reg_int(s1, src->prev, REG_ITMP1);
1002 var_to_reg_int(s2, src, REG_ITMP2);
1003 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1004 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1005 M_SRA(s1, REG_ITMP3, d);
1006 store_reg_to_var_int(iptr->dst, d);
1009 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1010 /* val.i = constant */
1012 var_to_reg_int(s1, src, REG_ITMP1);
1013 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1014 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1015 store_reg_to_var_int(iptr->dst, d);
1018 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1020 var_to_reg_int(s1, src->prev, REG_ITMP1);
1021 var_to_reg_int(s2, src, REG_ITMP2);
1022 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1023 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1024 M_SRL(s1, REG_ITMP2, d);
1025 store_reg_to_var_int(iptr->dst, d);
1028 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1029 /* val.i = constant */
1031 var_to_reg_int(s1, src, REG_ITMP1);
1032 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1033 if (iptr->val.i & 0x1f)
1034 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1037 store_reg_to_var_int(iptr->dst, d);
1040 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1042 var_to_reg_int(s1, src->prev, REG_ITMP1);
1043 var_to_reg_int(s2, src, REG_ITMP2);
1044 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1046 store_reg_to_var_int(iptr->dst, d);
1049 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1050 /* val.i = constant */
1052 var_to_reg_int(s1, src, REG_ITMP1);
1053 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1054 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1055 M_AND_IMM(s1, iptr->val.i, d);
1058 else if (iptr->val.i == 0xffffff) {
1059 M_RLWINM(s1, 0, 8, 31, d);
1063 ICONST(REG_ITMP2, iptr->val.i);
1064 M_AND(s1, REG_ITMP2, d);
1066 store_reg_to_var_int(iptr->dst, d);
1069 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1071 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1072 var_to_reg_int_low(s2, src, REG_ITMP2);
1073 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1074 M_AND(s1, s2, GET_LOW_REG(d));
1075 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1076 var_to_reg_int_high(s2, src, REG_ITMP3);
1077 M_AND(s1, s2, GET_HIGH_REG(d));
1078 store_reg_to_var_int(iptr->dst, d);
1081 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1082 /* val.l = constant */
1084 s3 = iptr->val.l & 0xffffffff;
1085 var_to_reg_int_low(s1, src, REG_ITMP1);
1086 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1087 if ((s3 >= 0) && (s3 <= 65535)) {
1088 M_AND_IMM(s1, s3, GET_LOW_REG(d));
1090 ICONST(REG_ITMP2, s3);
1091 M_AND(s1, REG_ITMP2, GET_LOW_REG(d));
1093 var_to_reg_int_high(s1, src, REG_ITMP1);
1094 s3 = iptr->val.l >> 32;
1095 if ((s3 >= 0) && (s3 <= 65535)) {
1096 M_AND_IMM(s1, s3, GET_HIGH_REG(d));
1099 ICONST(REG_ITMP3, s3);
1100 M_AND(s1, REG_ITMP3, GET_HIGH_REG(d));
1102 store_reg_to_var_int(iptr->dst, d);
1105 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1106 /* val.i = constant */
1108 var_to_reg_int(s1, src, REG_ITMP1);
1109 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1110 M_MOV(s1, REG_ITMP2);
1112 M_BGE(1 + 2*(iptr->val.i >= 32768));
1113 if (iptr->val.i >= 32768) {
1114 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1115 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1116 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1118 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1120 int b=0, m = iptr->val.i;
1123 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1125 M_ISUB(s1, REG_ITMP2, d);
1126 store_reg_to_var_int(iptr->dst, d);
1129 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1131 var_to_reg_int(s1, src->prev, REG_ITMP1);
1132 var_to_reg_int(s2, src, REG_ITMP2);
1133 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1135 store_reg_to_var_int(iptr->dst, d);
1138 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1139 /* val.i = constant */
1141 var_to_reg_int(s1, src, REG_ITMP1);
1142 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1143 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1144 M_OR_IMM(s1, iptr->val.i, d);
1147 ICONST(REG_ITMP2, iptr->val.i);
1148 M_OR(s1, REG_ITMP2, d);
1150 store_reg_to_var_int(iptr->dst, d);
1153 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1155 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1156 var_to_reg_int_low(s2, src, REG_ITMP2);
1157 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1158 M_OR(s1, s2, GET_LOW_REG(d));
1159 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1160 var_to_reg_int_high(s2, src, REG_ITMP3);
1161 M_OR(s1, s2, GET_HIGH_REG(d));
1162 store_reg_to_var_int(iptr->dst, d);
1165 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1166 /* val.l = constant */
1168 s3 = iptr->val.l & 0xffffffff;
1169 var_to_reg_int_low(s1, src, REG_ITMP1);
1170 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1171 if ((s3 >= 0) && (s3 <= 65535)) {
1172 M_OR_IMM(s1, s3, GET_LOW_REG(d));
1174 ICONST(REG_ITMP2, s3);
1175 M_OR(s1, REG_ITMP2, GET_LOW_REG(d));
1177 var_to_reg_int_high(s1, src, REG_ITMP1);
1178 s3 = iptr->val.l >> 32;
1179 if ((s3 >= 0) && (s3 <= 65535)) {
1180 M_OR_IMM(s1, s3, GET_HIGH_REG(d));
1182 ICONST(REG_ITMP3, s3);
1183 M_OR(s1, REG_ITMP3, GET_HIGH_REG(d));
1185 store_reg_to_var_int(iptr->dst, d);
1188 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1190 var_to_reg_int(s1, src->prev, REG_ITMP1);
1191 var_to_reg_int(s2, src, REG_ITMP2);
1192 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1194 store_reg_to_var_int(iptr->dst, d);
1197 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1198 /* val.i = constant */
1200 var_to_reg_int(s1, src, REG_ITMP1);
1201 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1202 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1203 M_XOR_IMM(s1, iptr->val.i, d);
1206 ICONST(REG_ITMP2, iptr->val.i);
1207 M_XOR(s1, REG_ITMP2, d);
1209 store_reg_to_var_int(iptr->dst, d);
1212 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1214 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1215 var_to_reg_int_low(s2, src, REG_ITMP2);
1216 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1217 M_XOR(s1, s2, GET_LOW_REG(d));
1218 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1219 var_to_reg_int_high(s2, src, REG_ITMP3);
1220 M_XOR(s1, s2, GET_HIGH_REG(d));
1221 store_reg_to_var_int(iptr->dst, d);
1224 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1225 /* val.l = constant */
1227 s3 = iptr->val.l & 0xffffffff;
1228 var_to_reg_int_low(s1, src, REG_ITMP1);
1229 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1230 if ((s3 >= 0) && (s3 <= 65535)) {
1231 M_XOR_IMM(s1, s3, GET_LOW_REG(d));
1233 ICONST(REG_ITMP2, s3);
1234 M_XOR(s1, REG_ITMP2, GET_LOW_REG(d));
1236 var_to_reg_int_high(s1, src, REG_ITMP1);
1237 s3 = iptr->val.l >> 32;
1238 if ((s3 >= 0) && (s3 <= 65535)) {
1239 M_XOR_IMM(s1, s3, GET_HIGH_REG(d));
1241 ICONST(REG_ITMP3, s3);
1242 M_XOR(s1, REG_ITMP3, GET_HIGH_REG(d));
1244 store_reg_to_var_int(iptr->dst, d);
1247 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1248 /*******************************************************************
1249 TODO: CHANGE THIS TO A VERSION THAT WORKS !!!
1250 *******************************************************************/
1251 var_to_reg_int_high(s1, src->prev, REG_ITMP3);
1252 var_to_reg_int_high(s2, src, REG_ITMP2);
1253 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1255 int tempreg = false;
1259 if (src->prev->flags & INMEMORY) {
1260 tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
1262 tempreg = tempreg || (d == GET_HIGH_REG(src->prev->regoff))
1263 || (d == GET_LOW_REG(src->prev->regoff));
1265 if (src->flags & INMEMORY) {
1266 tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
1268 tempreg = tempreg || (d == GET_HIGH_REG(src->regoff))
1269 || (d == GET_LOW_REG(src->regoff));
1272 dreg = tempreg ? REG_ITMP1 : d;
1273 M_IADD_IMM(REG_ZERO, 1, dreg);
1278 var_to_reg_int_low(s1, src->prev, REG_ITMP3);
1279 var_to_reg_int_low(s2, src, REG_ITMP2);
1283 M_IADD_IMM(dreg, -1, dreg);
1284 M_IADD_IMM(dreg, -1, dreg);
1285 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1286 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1289 store_reg_to_var_int(iptr->dst, d);
1292 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1293 /* op1 = variable, val.i = constant */
1295 var = &(rd->locals[iptr->op1][TYPE_INT]);
1296 if (var->flags & INMEMORY) {
1298 M_ILD(s1, REG_SP, var->regoff * 4);
1306 M_ADDIS(s1, m>>16, s1);
1308 M_IADD_IMM(s1, m&0xffff, s1);
1310 if (var->flags & INMEMORY)
1311 M_IST(s1, REG_SP, var->regoff * 4);
1315 /* floating operations ************************************************/
1317 case ICMD_FNEG: /* ..., value ==> ..., - value */
1319 var_to_reg_flt(s1, src, REG_FTMP1);
1320 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1322 store_reg_to_var_flt(iptr->dst, d);
1325 case ICMD_DNEG: /* ..., value ==> ..., - value */
1327 var_to_reg_flt(s1, src, REG_FTMP1);
1328 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1330 store_reg_to_var_flt(iptr->dst, d);
1333 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1335 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1336 var_to_reg_flt(s2, src, REG_FTMP2);
1337 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1339 store_reg_to_var_flt(iptr->dst, d);
1342 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1344 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1345 var_to_reg_flt(s2, src, REG_FTMP2);
1346 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1348 store_reg_to_var_flt(iptr->dst, d);
1351 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1353 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1354 var_to_reg_flt(s2, src, REG_FTMP2);
1355 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1357 store_reg_to_var_flt(iptr->dst, d);
1360 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1362 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1363 var_to_reg_flt(s2, src, REG_FTMP2);
1364 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1366 store_reg_to_var_flt(iptr->dst, d);
1369 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1371 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1372 var_to_reg_flt(s2, src, REG_FTMP2);
1373 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1375 store_reg_to_var_flt(iptr->dst, d);
1378 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1380 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1381 var_to_reg_flt(s2, src, REG_FTMP2);
1382 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1384 store_reg_to_var_flt(iptr->dst, d);
1387 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1389 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1390 var_to_reg_flt(s2, src, REG_FTMP2);
1391 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1393 store_reg_to_var_flt(iptr->dst, d);
1396 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1398 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1399 var_to_reg_flt(s2, src, REG_FTMP2);
1400 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1402 store_reg_to_var_flt(iptr->dst, d);
1405 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1407 var_to_reg_flt(s1, src, REG_FTMP1);
1408 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1410 a = dseg_addfloat(cd, 0.0);
1411 M_FLD(REG_FTMP2, REG_PV, a);
1412 M_FCMPU(s1, REG_FTMP2);
1414 a = dseg_adds4(cd, 0);
1415 M_CVTDL_C(s1, REG_FTMP1);
1416 M_LDA (REG_ITMP1, REG_PV, a);
1417 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1418 M_ILD (d, REG_PV, a);
1419 store_reg_to_var_int(iptr->dst, d);
1422 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1424 var_to_reg_flt(s1, src, REG_FTMP1);
1425 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1427 store_reg_to_var_flt(iptr->dst, d);
1430 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1432 var_to_reg_flt(s1, src, REG_FTMP1);
1433 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1435 store_reg_to_var_flt(iptr->dst, d);
1438 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1440 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1441 var_to_reg_flt(s2, src, REG_FTMP2);
1442 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1444 M_IADD_IMM(0, -1, d);
1447 M_IADD_IMM(0, 0, d);
1449 M_IADD_IMM(0, 1, d);
1450 store_reg_to_var_int(iptr->dst, d);
1453 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1455 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1456 var_to_reg_flt(s2, src, REG_FTMP2);
1457 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1459 M_IADD_IMM(0, 1, d);
1462 M_IADD_IMM(0, 0, d);
1464 M_IADD_IMM(0, -1, d);
1465 store_reg_to_var_int(iptr->dst, d);
1469 /* memory operations **************************************************/
1471 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1473 var_to_reg_int(s1, src, REG_ITMP1);
1474 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1475 gen_nullptr_check(s1);
1476 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1477 store_reg_to_var_int(iptr->dst, d);
1480 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1482 var_to_reg_int(s1, src->prev, REG_ITMP1);
1483 var_to_reg_int(s2, src, REG_ITMP2);
1484 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1485 if (iptr->op1 == 0) {
1486 gen_nullptr_check(s1);
1489 M_SLL_IMM(s2, 2, REG_ITMP2);
1490 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1491 M_LWZX(d, s1, REG_ITMP2);
1492 store_reg_to_var_int(iptr->dst, d);
1495 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1497 var_to_reg_int(s1, src->prev, REG_ITMP1);
1498 var_to_reg_int(s2, src, REG_ITMP2);
1499 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1500 if (iptr->op1 == 0) {
1501 gen_nullptr_check(s1);
1504 M_SLL_IMM(s2, 3, REG_ITMP2);
1505 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1506 M_ILD(GET_HIGH_REG(d), REG_ITMP2, OFFSET(java_longarray, data[0]));
1507 M_ILD(GET_LOW_REG(d), REG_ITMP2, OFFSET(java_longarray,
1509 store_reg_to_var_int(iptr->dst, d);
1512 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1514 var_to_reg_int(s1, src->prev, REG_ITMP1);
1515 var_to_reg_int(s2, src, REG_ITMP2);
1516 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1517 if (iptr->op1 == 0) {
1518 gen_nullptr_check(s1);
1521 M_SLL_IMM(s2, 2, REG_ITMP2);
1522 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1523 M_LWZX(d, s1, REG_ITMP2);
1524 store_reg_to_var_int(iptr->dst, d);
1527 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1529 var_to_reg_int(s1, src->prev, REG_ITMP1);
1530 var_to_reg_int(s2, src, REG_ITMP2);
1531 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1532 if (iptr->op1 == 0) {
1533 gen_nullptr_check(s1);
1536 M_SLL_IMM(s2, 2, REG_ITMP2);
1537 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1538 M_LFSX(d, s1, REG_ITMP2);
1539 store_reg_to_var_flt(iptr->dst, d);
1542 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1544 var_to_reg_int(s1, src->prev, REG_ITMP1);
1545 var_to_reg_int(s2, src, REG_ITMP2);
1546 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1547 if (iptr->op1 == 0) {
1548 gen_nullptr_check(s1);
1551 M_SLL_IMM(s2, 3, REG_ITMP2);
1552 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1553 M_LFDX(d, s1, REG_ITMP2);
1554 store_reg_to_var_flt(iptr->dst, d);
1557 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1559 var_to_reg_int(s1, src->prev, REG_ITMP1);
1560 var_to_reg_int(s2, src, REG_ITMP2);
1561 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1562 if (iptr->op1 == 0) {
1563 gen_nullptr_check(s1);
1566 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1567 M_LBZX(d, s1, REG_ITMP2);
1569 store_reg_to_var_int(iptr->dst, d);
1572 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1574 var_to_reg_int(s1, src->prev, REG_ITMP1);
1575 var_to_reg_int(s2, src, REG_ITMP2);
1576 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1577 if (iptr->op1 == 0) {
1578 gen_nullptr_check(s1);
1581 M_SLL_IMM(s2, 1, REG_ITMP2);
1582 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1583 M_LHAX(d, s1, REG_ITMP2);
1584 store_reg_to_var_int(iptr->dst, d);
1587 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1589 var_to_reg_int(s1, src->prev, REG_ITMP1);
1590 var_to_reg_int(s2, src, REG_ITMP2);
1591 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1592 if (iptr->op1 == 0) {
1593 gen_nullptr_check(s1);
1596 M_SLL_IMM(s2, 1, REG_ITMP2);
1597 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1598 M_LHZX(d, s1, REG_ITMP2);
1599 store_reg_to_var_int(iptr->dst, d);
1602 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1604 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1605 var_to_reg_int(s2, src->prev, REG_ITMP2);
1606 if (iptr->op1 == 0) {
1607 gen_nullptr_check(s1);
1610 var_to_reg_int_high(s3, src, REG_ITMP3);
1611 M_SLL_IMM(s2, 3, REG_ITMP2);
1612 M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
1613 M_STWX(s3, s1, REG_ITMP2);
1614 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1615 var_to_reg_int_low(s3, src, REG_ITMP3);
1616 M_STWX(s3, s1, REG_ITMP2);
1619 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1621 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1622 var_to_reg_int(s2, src->prev, REG_ITMP2);
1623 if (iptr->op1 == 0) {
1624 gen_nullptr_check(s1);
1627 var_to_reg_int(s3, src, REG_ITMP3);
1628 M_SLL_IMM(s2, 2, REG_ITMP2);
1629 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1630 M_STWX(s3, s1, REG_ITMP2);
1633 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1635 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1636 var_to_reg_int(s2, src->prev, REG_ITMP2);
1637 if (iptr->op1 == 0) {
1638 gen_nullptr_check(s1);
1641 var_to_reg_flt(s3, src, REG_FTMP3);
1642 M_SLL_IMM(s2, 2, REG_ITMP2);
1643 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1644 M_STFSX(s3, s1, REG_ITMP2);
1647 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1649 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1650 var_to_reg_int(s2, src->prev, REG_ITMP2);
1651 if (iptr->op1 == 0) {
1652 gen_nullptr_check(s1);
1655 var_to_reg_flt(s3, src, REG_FTMP3);
1656 M_SLL_IMM(s2, 3, REG_ITMP2);
1657 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1658 M_STFDX(s3, s1, REG_ITMP2);
1661 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1663 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1664 var_to_reg_int(s2, src->prev, REG_ITMP2);
1665 if (iptr->op1 == 0) {
1666 gen_nullptr_check(s1);
1669 var_to_reg_int(s3, src, REG_ITMP3);
1670 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1671 M_STBX(s3, s1, REG_ITMP2);
1674 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1676 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1677 var_to_reg_int(s2, src->prev, REG_ITMP2);
1678 if (iptr->op1 == 0) {
1679 gen_nullptr_check(s1);
1682 var_to_reg_int(s3, src, REG_ITMP3);
1683 M_SLL_IMM(s2, 1, REG_ITMP2);
1684 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1685 M_STHX(s3, s1, REG_ITMP2);
1688 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1690 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1691 var_to_reg_int(s2, src->prev, REG_ITMP2);
1692 if (iptr->op1 == 0) {
1693 gen_nullptr_check(s1);
1696 var_to_reg_int(s3, src, REG_ITMP3);
1697 M_SLL_IMM(s2, 1, REG_ITMP2);
1698 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1699 M_STHX(s3, s1, REG_ITMP2);
1703 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1705 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1706 var_to_reg_int(s2, src->prev, REG_ITMP2);
1707 /* if (iptr->op1 == 0) { */
1708 gen_nullptr_check(s1);
1711 var_to_reg_int(s3, src, REG_ITMP3);
1713 M_MOV(s1, rd->argintregs[0]);
1714 M_MOV(s3, rd->argintregs[1]);
1716 disp = dseg_addaddress(cd, bte->fp);
1717 M_ALD(REG_ITMP1, REG_PV, disp);
1722 codegen_addxstorerefs(cd, mcodeptr);
1724 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1725 var_to_reg_int(s2, src->prev, REG_ITMP2);
1726 var_to_reg_int(s3, src, REG_ITMP3);
1727 M_SLL_IMM(s2, 2, REG_ITMP2);
1728 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1729 M_STWX(s3, s1, REG_ITMP2);
1733 case ICMD_GETSTATIC: /* ... ==> ..., value */
1734 /* op1 = type, val.a = field address */
1737 codegen_addpatchref(cd, mcodeptr,
1738 PATCHER_get_putstatic,
1739 (unresolved_field *) iptr->target);
1741 if (opt_showdisassemble)
1747 fieldinfo *fi = iptr->val.a;
1749 if (!fi->class->initialized) {
1750 codegen_addpatchref(cd, mcodeptr,
1751 PATCHER_clinit, fi->class);
1753 if (opt_showdisassemble)
1757 a = (ptrint) &(fi->value);
1760 a = dseg_addaddress(cd, a);
1761 M_ALD(REG_ITMP1, REG_PV, a);
1762 switch (iptr->op1) {
1764 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1765 M_ILD(d, REG_ITMP1, 0);
1766 store_reg_to_var_int(iptr->dst, d);
1769 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1770 M_ILD(GET_HIGH_REG(d), REG_ITMP1, 0);
1771 M_ILD(GET_LOW_REG(d), REG_ITMP1, 4);
1772 store_reg_to_var_int(iptr->dst, d);
1775 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1776 M_ALD(d, REG_ITMP1, 0);
1777 store_reg_to_var_int(iptr->dst, d);
1780 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1781 M_FLD(d, REG_ITMP1, 0);
1782 store_reg_to_var_flt(iptr->dst, d);
1785 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1786 M_DLD(d, REG_ITMP1, 0);
1787 store_reg_to_var_flt(iptr->dst, d);
1792 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1793 /* op1 = type, val.a = field address */
1797 codegen_addpatchref(cd, mcodeptr,
1798 PATCHER_get_putstatic,
1799 (unresolved_field *) iptr->target);
1801 if (opt_showdisassemble)
1807 fieldinfo *fi = iptr->val.a;
1809 if (!fi->class->initialized) {
1810 codegen_addpatchref(cd, mcodeptr,
1811 PATCHER_clinit, fi->class);
1813 if (opt_showdisassemble)
1817 a = (ptrint) &(fi->value);
1820 disp = dseg_addaddress(cd, a);
1821 M_ALD(REG_ITMP1, REG_PV, disp);
1822 switch (iptr->op1) {
1824 var_to_reg_int(s2, src, REG_ITMP2);
1825 M_IST(s2, REG_ITMP1, 0);
1828 var_to_reg_int(s2, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
1829 M_IST(GET_HIGH_REG(s2), REG_ITMP1, 0);
1830 M_IST(GET_LOW_REG(s2), REG_ITMP1, 4);
1833 var_to_reg_int(s2, src, REG_ITMP2);
1834 M_AST(s2, REG_ITMP1, 0);
1837 var_to_reg_flt(s2, src, REG_FTMP2);
1838 M_FST(s2, REG_ITMP1, 0);
1841 var_to_reg_flt(s2, src, REG_FTMP2);
1842 M_DST(s2, REG_ITMP1, 0);
1848 case ICMD_GETFIELD: /* ... ==> ..., value */
1849 /* op1 = type, val.i = field offset */
1851 var_to_reg_int(s1, src, REG_ITMP1);
1852 gen_nullptr_check(s1);
1855 codegen_addpatchref(cd, mcodeptr,
1856 PATCHER_get_putfield,
1857 (unresolved_field *) iptr->target);
1859 if (opt_showdisassemble)
1865 a = ((fieldinfo *) (iptr->val.a))->offset;
1868 switch (iptr->op1) {
1870 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1872 store_reg_to_var_int(iptr->dst, d);
1875 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1876 M_ILD(GET_HIGH_REG(d), s1, a);
1877 M_ILD(GET_LOW_REG(d), s1, a + 4);
1878 store_reg_to_var_int(iptr->dst, d);
1881 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1883 store_reg_to_var_int(iptr->dst, d);
1886 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1888 store_reg_to_var_flt(iptr->dst, d);
1891 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1893 store_reg_to_var_flt(iptr->dst, d);
1898 case ICMD_PUTFIELD: /* ..., value ==> ... */
1899 /* op1 = type, val.i = field offset */
1901 var_to_reg_int(s1, src->prev, REG_ITMP1);
1902 gen_nullptr_check(s1);
1904 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
1905 if (IS_2_WORD_TYPE(iptr->op1)) {
1906 var_to_reg_int(s2, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
1908 var_to_reg_int(s2, src, REG_ITMP2);
1911 var_to_reg_flt(s2, src, REG_FTMP2);
1915 codegen_addpatchref(cd, mcodeptr,
1916 PATCHER_get_putfield,
1917 (unresolved_field *) iptr->target);
1919 if (opt_showdisassemble)
1925 a = ((fieldinfo *) (iptr->val.a))->offset;
1928 switch (iptr->op1) {
1933 M_IST(GET_HIGH_REG(s2), s1, a);
1934 M_IST(GET_LOW_REG(s2), s1, a + 4);
1949 /* branch operations **************************************************/
1951 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1953 disp = dseg_addaddress(cd, asm_handle_exception);
1954 M_ALD(REG_ITMP2, REG_PV, disp);
1956 var_to_reg_int(s1, src, REG_ITMP1);
1957 M_INTMOVE(s1, REG_ITMP1_XPTR);
1959 if (m->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
1960 M_BL(0); /* get current PC */
1961 M_MFLR(REG_ITMP2_XPC);
1962 if (m->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
1963 M_RTS; /* jump to CTR */
1968 case ICMD_GOTO: /* ... ==> ... */
1969 /* op1 = target JavaVM pc */
1971 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1975 case ICMD_JSR: /* ... ==> ... */
1976 /* op1 = target JavaVM pc */
1978 if (m->isleafmethod) M_MFLR(REG_ITMP2);
1981 M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
1982 if (m->isleafmethod) M_MTLR(REG_ITMP2);
1984 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1987 case ICMD_RET: /* ... ==> ... */
1988 /* op1 = local variable */
1990 var = &(rd->locals[iptr->op1][TYPE_ADR]);
1991 if (var->flags & INMEMORY) {
1992 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
1995 M_MTCTR(var->regoff);
2000 case ICMD_IFNULL: /* ..., value ==> ... */
2001 /* op1 = target JavaVM pc */
2003 var_to_reg_int(s1, src, REG_ITMP1);
2006 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2009 case ICMD_IFNONNULL: /* ..., value ==> ... */
2010 /* op1 = target JavaVM pc */
2012 var_to_reg_int(s1, src, REG_ITMP1);
2015 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2023 case ICMD_IFEQ: /* ..., value ==> ... */
2024 /* op1 = target JavaVM pc, val.i = constant */
2026 var_to_reg_int(s1, src, REG_ITMP1);
2027 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2028 M_CMPI(s1, iptr->val.i);
2031 ICONST(REG_ITMP2, iptr->val.i);
2032 M_CMP(s1, REG_ITMP2);
2055 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2059 case ICMD_IF_LEQ: /* ..., value ==> ... */
2060 /* op1 = target JavaVM pc, val.l = constant */
2062 var_to_reg_int_low(s1, src, REG_ITMP1);
2063 var_to_reg_int_high(s2, src, REG_ITMP2);
2064 if (iptr->val.l == 0) {
2065 M_OR(s1, s2, REG_ITMP3);
2066 M_CMPI(REG_ITMP3, 0);
2068 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2069 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2071 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2074 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2075 M_CMP(s2, REG_ITMP3);
2077 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2078 M_CMP(s1, REG_ITMP3)
2081 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2084 case ICMD_IF_LLT: /* ..., value ==> ... */
2085 /* op1 = target JavaVM pc, val.l = constant */
2086 var_to_reg_int_low(s1, src, REG_ITMP1);
2087 var_to_reg_int_high(s2, src, REG_ITMP2);
2088 /* if (iptr->val.l == 0) { */
2089 /* M_OR(s1, s2, REG_ITMP3); */
2090 /* M_CMPI(REG_ITMP3, 0); */
2093 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2094 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2096 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2098 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2101 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2102 M_CMP(s2, REG_ITMP3);
2104 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2106 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2107 M_CMP(s1, REG_ITMP3)
2110 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2113 case ICMD_IF_LLE: /* ..., value ==> ... */
2114 /* op1 = target JavaVM pc, val.l = constant */
2116 var_to_reg_int_low(s1, src, REG_ITMP1);
2117 var_to_reg_int_high(s2, src, REG_ITMP2);
2118 /* if (iptr->val.l == 0) { */
2119 /* M_OR(s1, s2, REG_ITMP3); */
2120 /* M_CMPI(REG_ITMP3, 0); */
2123 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2124 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2126 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2128 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2131 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2132 M_CMP(s2, REG_ITMP3);
2134 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2136 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2137 M_CMP(s1, REG_ITMP3)
2140 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2143 case ICMD_IF_LNE: /* ..., value ==> ... */
2144 /* op1 = target JavaVM pc, val.l = constant */
2146 var_to_reg_int_low(s1, src, REG_ITMP1);
2147 var_to_reg_int_high(s2, src, REG_ITMP2);
2148 if (iptr->val.l == 0) {
2149 M_OR(s1, s2, REG_ITMP3);
2150 M_CMPI(REG_ITMP3, 0);
2152 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2153 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2155 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2158 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2159 M_CMP(s2, REG_ITMP3);
2161 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2162 M_CMP(s1, REG_ITMP3)
2165 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2168 case ICMD_IF_LGT: /* ..., value ==> ... */
2169 /* op1 = target JavaVM pc, val.l = constant */
2171 var_to_reg_int_low(s1, src, REG_ITMP1);
2172 var_to_reg_int_high(s2, src, REG_ITMP2);
2173 /* if (iptr->val.l == 0) { */
2174 /* M_OR(s1, s2, REG_ITMP3); */
2175 /* M_CMPI(REG_ITMP3, 0); */
2178 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2179 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2181 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2183 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2186 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2187 M_CMP(s2, REG_ITMP3);
2189 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2191 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2192 M_CMP(s1, REG_ITMP3)
2195 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2198 case ICMD_IF_LGE: /* ..., value ==> ... */
2199 /* op1 = target JavaVM pc, val.l = constant */
2200 var_to_reg_int_low(s1, src, REG_ITMP1);
2201 var_to_reg_int_high(s2, src, REG_ITMP2);
2202 /* if (iptr->val.l == 0) { */
2203 /* M_OR(s1, s2, REG_ITMP3); */
2204 /* M_CMPI(REG_ITMP3, 0); */
2207 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2208 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2210 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2212 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2215 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2216 M_CMP(s2, REG_ITMP3);
2218 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2220 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2221 M_CMP(s1, REG_ITMP3)
2224 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2228 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2229 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2230 /******************************************************************
2231 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2232 *******************************************************************/
2233 case ICMD_IF_ACMPEQ:
2235 var_to_reg_int(s1, src->prev, REG_ITMP1);
2236 var_to_reg_int(s2, src, REG_ITMP2);
2239 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2242 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2243 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2244 /******************************************************************
2245 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2246 *******************************************************************/
2247 case ICMD_IF_ACMPNE:
2249 var_to_reg_int(s1, src->prev, REG_ITMP1);
2250 var_to_reg_int(s2, src, REG_ITMP2);
2253 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2256 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2257 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2258 /******************************************************************
2259 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2260 *******************************************************************/
2262 var_to_reg_int(s1, src->prev, REG_ITMP1);
2263 var_to_reg_int(s2, src, REG_ITMP2);
2266 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2269 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2270 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2271 /******************************************************************
2272 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2273 *******************************************************************/
2275 var_to_reg_int(s1, src->prev, REG_ITMP1);
2276 var_to_reg_int(s2, src, REG_ITMP2);
2279 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2282 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2283 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2284 /******************************************************************
2285 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2286 *******************************************************************/
2288 var_to_reg_int(s1, src->prev, REG_ITMP1);
2289 var_to_reg_int(s2, src, REG_ITMP2);
2292 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2295 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2296 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2297 /******************************************************************
2298 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2299 *******************************************************************/
2301 var_to_reg_int(s1, src->prev, REG_ITMP1);
2302 var_to_reg_int(s2, src, REG_ITMP2);
2305 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2308 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2310 var_to_reg_int(s1, src, REG_RESULT);
2311 M_TINTMOVE(src->type, s1, REG_RESULT);
2312 goto nowperformreturn;
2314 var_to_reg_int(s1, src, PACK_REGS(REG_RESULT2, REG_RESULT));
2315 M_TINTMOVE(src->type, s1, PACK_REGS(REG_RESULT2, REG_RESULT));
2316 goto nowperformreturn;
2318 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2320 var_to_reg_flt(s1, src, REG_FRESULT);
2321 M_FLTMOVE(s1, REG_FRESULT);
2322 goto nowperformreturn;
2324 case ICMD_RETURN: /* ... ==> ... */
2330 p = parentargs_base;
2332 /* call trace function */
2336 M_LDA(REG_SP, REG_SP, -10 * 8);
2337 M_DST(REG_FRESULT, REG_SP, 48+0);
2338 M_IST(REG_RESULT, REG_SP, 48+8);
2339 M_AST(REG_ITMP3, REG_SP, 48+12);
2340 M_IST(REG_RESULT2, REG_SP, 48+16);
2342 /* keep this order */
2343 switch (iptr->opc) {
2346 #if defined(__DARWIN__)
2347 M_MOV(REG_RESULT, rd->argintregs[2]);
2348 M_CLR(rd->argintregs[1]);
2350 M_MOV(REG_RESULT, rd->argintregs[3]);
2351 M_CLR(rd->argintregs[2]);
2356 #if defined(__DARWIN__)
2357 M_MOV(REG_RESULT2, rd->argintregs[2]);
2358 M_MOV(REG_RESULT, rd->argintregs[1]);
2360 M_MOV(REG_RESULT2, rd->argintregs[3]);
2361 M_MOV(REG_RESULT, rd->argintregs[2]);
2366 a = dseg_addaddress(cd, m);
2367 M_ALD(rd->argintregs[0], REG_PV, a);
2369 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2370 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2371 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2372 M_ALD(REG_ITMP2, REG_PV, a);
2375 M_DLD(REG_FRESULT, REG_SP, 48+0);
2376 M_ILD(REG_RESULT, REG_SP, 48+8);
2377 M_ALD(REG_ITMP3, REG_SP, 48+12);
2378 M_ILD(REG_RESULT2, REG_SP, 48+16);
2379 M_LDA(REG_SP, REG_SP, 10 * 8);
2383 #if defined(USE_THREADS)
2384 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2385 /* we need to save the proper return value */
2386 switch (iptr->opc) {
2388 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2392 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2395 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2398 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2402 a = dseg_addaddress(cd, BUILTIN_monitorexit);
2403 M_ALD(REG_ITMP3, REG_PV, a);
2405 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 4);
2408 /* and now restore the proper return value */
2409 switch (iptr->opc) {
2411 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2415 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2418 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2421 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2427 /* restore return address */
2429 if (!m->isleafmethod) {
2430 M_ALD(REG_ITMP3, REG_SP, p * 4 + LA_LR_OFFSET);
2434 /* restore saved registers */
2436 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2437 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2439 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2440 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2443 /* deallocate stack */
2445 if (parentargs_base)
2446 M_LDA(REG_SP, REG_SP, parentargs_base * 4);
2454 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2459 tptr = (void **) iptr->target;
2461 s4ptr = iptr->val.a;
2462 l = s4ptr[1]; /* low */
2463 i = s4ptr[2]; /* high */
2465 var_to_reg_int(s1, src, REG_ITMP1);
2467 M_INTMOVE(s1, REG_ITMP1);
2468 } else if (l <= 32768) {
2469 M_LDA(REG_ITMP1, s1, -l);
2471 ICONST(REG_ITMP2, l);
2472 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2478 M_CMPUI(REG_ITMP1, i - 1);
2481 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2482 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2484 /* build jump table top down and use address of lowest entry */
2486 /* s4ptr += 3 + i; */
2490 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2491 dseg_addtarget(cd, (basicblock *) tptr[0]);
2496 /* length of dataseg after last dseg_addtarget is used by load */
2498 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2499 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2500 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2507 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2509 s4 i, l, val, *s4ptr;
2512 tptr = (void **) iptr->target;
2514 s4ptr = iptr->val.a;
2515 l = s4ptr[0]; /* default */
2516 i = s4ptr[1]; /* count */
2518 MCODECHECK((i<<2)+8);
2519 var_to_reg_int(s1, src, REG_ITMP1);
2525 if ((val >= -32768) && (val <= 32767)) {
2529 a = dseg_adds4(cd, val);
2530 M_ILD(REG_ITMP2, REG_PV, a);
2531 M_CMP(s1, REG_ITMP2);
2534 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2535 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2539 /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2541 tptr = (void **) iptr->target;
2542 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2549 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2550 /* op1 = arg count val.a = builtintable entry */
2556 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2557 /* op1 = arg count, val.a = method pointer */
2559 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2560 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2561 case ICMD_INVOKEINTERFACE:
2566 md = lm->parseddesc;
2568 unresolved_method *um = iptr->target;
2569 md = um->methodref->parseddesc.md;
2575 MCODECHECK((s3 << 1) + 64);
2577 /* copy arguments to registers or stack location */
2579 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2580 if (src->varkind == ARGVAR)
2582 if (IS_INT_LNG_TYPE(src->type)) {
2583 if (!md->params[s3].inmemory) {
2584 if (IS_2_WORD_TYPE(src->type))
2586 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2587 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]);
2589 s1 = rd->argintregs[md->params[s3].regoff];
2590 var_to_reg_int(d, src, s1);
2591 M_TINTMOVE(src->type, d, s1);
2593 var_to_reg_int(d, src, PACK_REGS(REG_ITMP3, REG_ITMP1));
2594 M_IST(GET_HIGH_REG(d), REG_SP,
2595 md->params[s3].regoff * 4);
2596 if (IS_2_WORD_TYPE(src->type))
2597 M_IST(GET_LOW_REG(d),
2598 REG_SP, md->params[s3].regoff * 4 + 4);
2602 if (!md->params[s3].inmemory) {
2603 s1 = rd->argfltregs[md->params[s3].regoff];
2604 var_to_reg_flt(d, src, s1);
2607 var_to_reg_flt(d, src, REG_FTMP1);
2608 if (IS_2_WORD_TYPE(src->type))
2609 M_DST(d, REG_SP, md->params[s3].regoff * 4);
2611 M_FST(d, REG_SP, md->params[s3].regoff * 4);
2616 switch (iptr->opc) {
2619 codegen_addpatchref(cd, mcodeptr, bte->fp, iptr->target);
2621 if (opt_showdisassemble)
2627 a = (ptrint) bte->fp;
2630 a = dseg_addaddress(cd, a);
2631 d = md->returntype.type;
2633 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2636 case ICMD_INVOKESPECIAL:
2637 gen_nullptr_check(rd->argintregs[0]);
2638 M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr */
2641 case ICMD_INVOKESTATIC:
2643 unresolved_method *um = iptr->target;
2645 codegen_addpatchref(cd, mcodeptr,
2646 PATCHER_invokestatic_special, um);
2648 if (opt_showdisassemble)
2652 d = md->returntype.type;
2655 a = (ptrint) lm->stubroutine;
2656 d = md->returntype.type;
2659 a = dseg_addaddress(cd, a);
2660 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
2663 case ICMD_INVOKEVIRTUAL:
2664 gen_nullptr_check(rd->argintregs[0]);
2667 unresolved_method *um = iptr->target;
2669 codegen_addpatchref(cd, mcodeptr,
2670 PATCHER_invokevirtual, um);
2672 if (opt_showdisassemble)
2676 d = md->returntype.type;
2679 s1 = OFFSET(vftbl_t, table[0]) +
2680 sizeof(methodptr) * lm->vftblindex;
2681 d = md->returntype.type;
2684 M_ALD(REG_METHODPTR, rd->argintregs[0],
2685 OFFSET(java_objectheader, vftbl));
2686 M_ALD(REG_PV, REG_METHODPTR, s1);
2689 case ICMD_INVOKEINTERFACE:
2690 gen_nullptr_check(rd->argintregs[0]);
2693 unresolved_method *um = iptr->target;
2695 codegen_addpatchref(cd, mcodeptr,
2696 PATCHER_invokeinterface, um);
2698 if (opt_showdisassemble)
2703 d = md->returntype.type;
2706 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2707 sizeof(methodptr*) * lm->class->index;
2709 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2711 d = md->returntype.type;
2714 M_ALD(REG_METHODPTR, rd->argintregs[0],
2715 OFFSET(java_objectheader, vftbl));
2716 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2717 M_ALD(REG_PV, REG_METHODPTR, s2);
2726 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2729 M_LDA(REG_PV, REG_ITMP1, -s1);
2731 s4 ml = -s1, mh = 0;
2732 while (ml < -32768) { ml += 65536; mh--; }
2733 M_LDA(REG_PV, REG_ITMP1, ml);
2734 M_LDAH(REG_PV, REG_PV, mh);
2737 /* d contains return type */
2739 if (d != TYPE_VOID) {
2740 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2741 if (IS_2_WORD_TYPE(iptr->dst->type)) {
2742 s1 = reg_of_var(rd, iptr->dst,
2743 PACK_REGS(REG_RESULT2, REG_RESULT));
2744 M_TINTMOVE(iptr->dst->type,
2745 PACK_REGS(REG_RESULT2, REG_RESULT), s1);
2747 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2748 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2750 store_reg_to_var_int(iptr->dst, s1);
2753 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2754 M_FLTMOVE(REG_FRESULT, s1);
2755 store_reg_to_var_flt(iptr->dst, s1);
2761 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2762 /* val.a: (classinfo*) superclass */
2764 /* superclass is an interface:
2766 * OK if ((sub == NULL) ||
2767 * (sub->vftbl->interfacetablelength > super->index) &&
2768 * (sub->vftbl->interfacetable[-super->index] != NULL));
2770 * superclass is a class:
2772 * OK if ((sub == NULL) || (0
2773 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2774 * super->vftbl->diffvall));
2779 vftbl_t *supervftbl;
2782 super = (classinfo *) iptr->val.a;
2789 superindex = super->index;
2790 supervftbl = super->vftbl;
2793 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2794 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
2796 var_to_reg_int(s1, src, REG_ITMP1);
2798 /* calculate interface checkcast code size */
2802 s2 += (opt_showdisassemble ? 1 : 0);
2804 /* calculate class checkcast code size */
2806 s3 = 8 + (s1 == REG_ITMP1);
2808 s3 += (opt_showdisassemble ? 1 : 0);
2810 /* if class is not resolved, check which code to call */
2814 M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
2816 codegen_addpatchref(cd, mcodeptr,
2817 PATCHER_checkcast_instanceof_flags,
2818 (constant_classref *) iptr->target);
2820 if (opt_showdisassemble)
2823 a = dseg_adds4(cd, 0); /* super->flags */
2824 M_ILD(REG_ITMP2, REG_PV, a);
2825 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2829 /* interface checkcast code */
2831 if (!super || (super->flags & ACC_INTERFACE)) {
2837 codegen_addpatchref(cd, mcodeptr,
2838 PATCHER_checkcast_instanceof_interface,
2839 (constant_classref *) iptr->target);
2841 if (opt_showdisassemble)
2845 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2846 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2847 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2849 codegen_addxcastrefs(cd, mcodeptr);
2850 M_ALD(REG_ITMP3, REG_ITMP2,
2851 OFFSET(vftbl_t, interfacetable[0]) -
2852 superindex * sizeof(methodptr*));
2855 codegen_addxcastrefs(cd, mcodeptr);
2861 /* class checkcast code */
2863 if (!super || !(super->flags & ACC_INTERFACE)) {
2869 codegen_addpatchref(cd, mcodeptr,
2870 PATCHER_checkcast_class,
2871 (constant_classref *) iptr->target);
2873 if (opt_showdisassemble)
2877 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2878 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2879 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
2881 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2882 a = dseg_addaddress(cd, supervftbl);
2883 M_ALD(REG_ITMP2, REG_PV, a);
2884 if (s1 != REG_ITMP1) {
2885 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2886 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2887 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2888 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2890 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2892 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2893 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2894 M_ALD(REG_ITMP2, REG_PV, a);
2895 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2896 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2897 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2900 M_CMPU(REG_ITMP3, REG_ITMP2);
2902 codegen_addxcastrefs(cd, mcodeptr);
2904 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2906 store_reg_to_var_int(iptr->dst, d);
2910 case ICMD_ARRAYCHECKCAST: /* ..., objectref ==> ..., objectref */
2911 /* op1: 1... resolved, 0... not resolved */
2913 var_to_reg_int(s1, src, REG_ITMP1);
2914 M_INTMOVE(s1, rd->argintregs[0]);
2919 codegen_addpatchref(cd, mcodeptr, bte->fp, iptr->target);
2921 if (opt_showdisassemble)
2927 a = (ptrint) bte->fp;
2930 disp = dseg_addaddress(cd, iptr->target);
2931 M_ALD(rd->argintregs[1], REG_PV, disp);
2932 disp = dseg_addaddress(cd, a);
2933 M_ALD(REG_ITMP2, REG_PV, disp);
2938 codegen_addxcastrefs(cd, mcodeptr);
2940 var_to_reg_int(s1, src, REG_ITMP1);
2941 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2943 store_reg_to_var_int(iptr->dst, d);
2947 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2948 /* val.a: (classinfo*) superclass */
2950 /* superclass is an interface:
2952 * return (sub != NULL) &&
2953 * (sub->vftbl->interfacetablelength > super->index) &&
2954 * (sub->vftbl->interfacetable[-super->index] != NULL);
2956 * superclass is a class:
2958 * return ((sub != NULL) && (0
2959 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2960 * super->vftbl->diffvall));
2965 vftbl_t *supervftbl;
2968 super = (classinfo *) iptr->val.a;
2975 superindex = super->index;
2976 supervftbl = super->vftbl;
2979 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2980 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2982 var_to_reg_int(s1, src, REG_ITMP1);
2983 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2985 M_MOV(s1, REG_ITMP1);
2989 /* calculate interface instanceof code size */
2993 s2 += (opt_showdisassemble ? 1 : 0);
2995 /* calculate class instanceof code size */
2999 s3 += (opt_showdisassemble ? 1 : 0);
3003 /* if class is not resolved, check which code to call */
3007 M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
3009 codegen_addpatchref(cd, mcodeptr,
3010 PATCHER_checkcast_instanceof_flags,
3011 (constant_classref *) iptr->target);
3013 if (opt_showdisassemble)
3016 a = dseg_adds4(cd, 0); /* super->flags */
3017 M_ILD(REG_ITMP2, REG_PV, a);
3018 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3022 /* interface instanceof code */
3024 if (!super || (super->flags & ACC_INTERFACE)) {
3030 codegen_addpatchref(cd, mcodeptr,
3031 PATCHER_checkcast_instanceof_interface,
3032 (constant_classref *) iptr->target);
3034 if (opt_showdisassemble)
3038 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3039 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3040 M_LDATST(REG_ITMP2, REG_ITMP2, -superindex);
3042 M_ALD(REG_ITMP1, REG_ITMP1,
3043 OFFSET(vftbl_t, interfacetable[0]) -
3044 superindex * sizeof(methodptr*));
3048 M_IADD_IMM(REG_ZERO, 1, d);
3054 /* class instanceof code */
3056 if (!super || !(super->flags & ACC_INTERFACE)) {
3062 codegen_addpatchref(cd, mcodeptr,
3063 PATCHER_instanceof_class,
3064 (constant_classref *) iptr->target);
3066 if (opt_showdisassemble) {
3071 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3072 a = dseg_addaddress(cd, supervftbl);
3073 M_ALD(REG_ITMP2, REG_PV, a);
3074 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3075 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3077 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3078 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3079 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3080 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3081 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3083 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3084 M_CMPU(REG_ITMP1, REG_ITMP2);
3087 M_IADD_IMM(REG_ZERO, 1, d);
3089 store_reg_to_var_int(iptr->dst, d);
3093 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3095 var_to_reg_int(s1, src, REG_ITMP1);
3098 codegen_addxcheckarefs(cd, mcodeptr);
3101 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3103 M_CMPI(REG_RESULT, 0);
3105 codegen_addxexceptionrefs(cd, mcodeptr);
3108 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3109 /* op1 = dimension, val.a = array descriptor */
3111 /* check for negative sizes and copy sizes to stack if necessary */
3113 MCODECHECK((iptr->op1 << 1) + 64);
3115 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3116 var_to_reg_int(s2, src, REG_ITMP1);
3119 codegen_addxcheckarefs(cd, mcodeptr);
3121 /* copy SAVEDVAR sizes to stack */
3123 if (src->varkind != ARGVAR)
3124 #if defined(__DARWIN__)
3125 M_IST(s2, REG_SP, LA_SIZE + (s1 + INT_ARG_CNT) * 4);
3127 M_IST(s2, REG_SP, LA_SIZE + (s1 + 3) * 4);
3131 /* is patcher function set? */
3134 codegen_addpatchref(cd, mcodeptr,
3135 (functionptr) iptr->target, iptr->val.a);
3137 if (opt_showdisassemble)
3143 a = (ptrint) iptr->val.a;
3146 /* a0 = dimension count */
3148 ICONST(rd->argintregs[0], iptr->op1);
3150 /* a1 = arraydescriptor */
3152 a = dseg_addaddress(cd, iptr->val.a);
3153 M_ALD(rd->argintregs[1], REG_PV, a);
3155 /* a2 = pointer to dimensions = stack pointer */
3157 #if defined(__DARWIN__)
3158 M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + INT_ARG_CNT * 4);
3160 M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + 3 * 4);
3163 a = dseg_addaddress(cd, BUILTIN_multianewarray);
3164 M_ALD(REG_PV, REG_PV, a);
3167 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3170 M_LDA (REG_PV, REG_ITMP1, -s1);
3172 s4 ml = -s1, mh = 0;
3173 while (ml < -32768) {ml += 65536; mh--;}
3174 M_LDA(REG_PV, REG_ITMP1, ml);
3175 M_LDAH(REG_PV, REG_PV, mh);
3177 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3178 M_INTMOVE(REG_RESULT, s1);
3179 store_reg_to_var_int(iptr->dst, s1);
3184 throw_cacao_exception_exit(string_java_lang_InternalError,
3185 "Unknown ICMD %d", iptr->opc);
3188 } /* for instruction */
3190 /* copy values to interface registers */
3192 src = bptr->outstack;
3193 len = bptr->outdepth;
3194 MCODECHECK(64 + len);
3200 if ((src->varkind != STACKVAR)) {
3202 if (IS_FLT_DBL_TYPE(s2)) {
3203 var_to_reg_flt(s1, src, REG_FTMP1);
3204 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3205 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3208 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3212 var_to_reg_int(s1, src, REG_ITMP1);
3213 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3214 M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3217 if (IS_2_WORD_TYPE(s2)) {
3218 M_IST(GET_HIGH_REG(s1),
3219 REG_SP, rd->interfaces[len][s2].regoff * 4);
3220 M_IST(GET_LOW_REG(s1), REG_SP,
3221 rd->interfaces[len][s2].regoff * 4 + 4);
3223 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3231 } /* if (bptr -> flags >= BBREACHED) */
3232 } /* for basic block */
3234 codegen_createlinenumbertable(cd);
3241 /* generate ArithemticException check stubs */
3245 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3246 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3247 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3249 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3253 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3255 (u1 *) mcodeptr - cd->mcodebase);
3259 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3261 if (xcodeptr != NULL) {
3262 disp = xcodeptr - mcodeptr - 1;
3266 xcodeptr = mcodeptr;
3268 if (m->isleafmethod) {
3270 M_AST(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3273 M_MOV(REG_PV, rd->argintregs[0]);
3274 M_MOV(REG_SP, rd->argintregs[1]);
3276 if (m->isleafmethod)
3277 M_MOV(REG_ITMP3, rd->argintregs[2]);
3279 M_ALD(rd->argintregs[2],
3280 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3282 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3284 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3285 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3287 disp = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
3288 M_ALD(REG_ITMP1, REG_PV, disp);
3291 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3293 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3294 M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3296 if (m->isleafmethod) {
3297 M_ALD(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3301 disp = dseg_addaddress(cd, asm_handle_exception);
3302 M_ALD(REG_ITMP3, REG_PV, disp);
3308 /* generate ArrayIndexOutOfBoundsException stubs */
3312 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3313 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3315 (u1 *) mcodeptr - cd->mcodebase);
3319 /* move index register into REG_ITMP1 */
3321 M_MOV(bref->reg, REG_ITMP1);
3323 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3325 if (xcodeptr != NULL) {
3326 disp = xcodeptr - mcodeptr - 1;
3330 xcodeptr = mcodeptr;
3332 if (m->isleafmethod) {
3334 M_AST(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3337 M_MOV(REG_PV, rd->argintregs[0]);
3338 M_MOV(REG_SP, rd->argintregs[1]);
3340 if (m->isleafmethod)
3341 M_MOV(REG_ITMP3, rd->argintregs[2]);
3343 M_ALD(rd->argintregs[2],
3344 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3346 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3347 M_MOV(REG_ITMP1, rd->argintregs[4]);
3349 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 6 * 4));
3350 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 4);
3352 disp = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
3353 M_ALD(REG_ITMP1, REG_PV, disp);
3356 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3358 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 4);
3359 M_IADD_IMM(REG_SP, LA_SIZE + 6 * 4, REG_SP);
3361 if (m->isleafmethod) {
3362 M_ALD(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3366 disp = dseg_addaddress(cd, asm_handle_exception);
3367 M_ALD(REG_ITMP3, REG_PV, disp);
3373 /* generate ArrayStoreException check stubs */
3377 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
3378 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3379 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3381 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3385 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3387 (u1 *) mcodeptr - cd->mcodebase);
3391 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3393 if (xcodeptr != NULL) {
3394 disp = xcodeptr - mcodeptr - 1;
3398 xcodeptr = mcodeptr;
3400 M_MOV(REG_PV, rd->argintregs[0]);
3401 M_MOV(REG_SP, rd->argintregs[1]);
3402 M_ALD(rd->argintregs[2],
3403 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3404 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3406 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3407 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3409 disp = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
3410 M_ALD(REG_ITMP1, REG_PV, disp);
3413 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3415 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3416 M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3418 disp = dseg_addaddress(cd, asm_handle_exception);
3419 M_ALD(REG_ITMP3, REG_PV, disp);
3425 /* generate ClassCastException stubs */
3429 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3430 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3431 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3433 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3437 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3439 (u1 *) mcodeptr - cd->mcodebase);
3443 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3445 if (xcodeptr != NULL) {
3446 disp = xcodeptr - mcodeptr - 1;
3450 xcodeptr = mcodeptr;
3452 if (m->isleafmethod) {
3454 M_AST(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3457 M_MOV(REG_PV, rd->argintregs[0]);
3458 M_MOV(REG_SP, rd->argintregs[1]);
3460 if (m->isleafmethod)
3461 M_MOV(REG_ITMP3, rd->argintregs[2]);
3463 M_ALD(rd->argintregs[2],
3464 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3466 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3468 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3469 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3471 disp = dseg_addaddress(cd, stacktrace_inline_classcastexception);
3472 M_ALD(REG_ITMP1, REG_PV, disp);
3475 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3477 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3478 M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3480 if (m->isleafmethod) {
3481 M_ALD(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3485 disp = dseg_addaddress(cd, asm_handle_exception);
3486 M_ALD(REG_ITMP3, REG_PV, disp);
3492 /* generate NegativeArraySizeException stubs */
3496 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3497 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3498 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3500 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3504 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3506 (u1 *) mcodeptr - cd->mcodebase);
3510 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3512 if (xcodeptr != NULL) {
3513 disp = xcodeptr - mcodeptr - 1;
3517 xcodeptr = mcodeptr;
3519 M_MOV(REG_PV, rd->argintregs[0]);
3520 M_MOV(REG_SP, rd->argintregs[1]);
3521 M_ALD(rd->argintregs[2],
3522 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3523 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3525 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3526 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3528 disp = dseg_addaddress(cd, stacktrace_inline_negativearraysizeexception);
3529 M_ALD(REG_ITMP1, REG_PV, disp);
3532 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3534 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3535 M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3537 disp = dseg_addaddress(cd, asm_handle_exception);
3538 M_ALD(REG_ITMP3, REG_PV, disp);
3544 /* generate NullPointerException stubs */
3548 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3549 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3550 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3552 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3556 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3558 (u1 *) mcodeptr - cd->mcodebase);
3562 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3564 if (xcodeptr != NULL) {
3565 disp = xcodeptr - mcodeptr - 1;
3569 xcodeptr = mcodeptr;
3571 if (m->isleafmethod) {
3573 M_AST(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3576 M_MOV(REG_PV, rd->argintregs[0]);
3577 M_MOV(REG_SP, rd->argintregs[1]);
3579 if (m->isleafmethod)
3580 M_MOV(REG_ITMP3, rd->argintregs[2]);
3582 M_ALD(rd->argintregs[2],
3583 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3585 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3587 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3588 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3590 disp = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
3591 M_ALD(REG_ITMP1, REG_PV, disp);
3594 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3596 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3597 M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3599 if (m->isleafmethod) {
3600 M_ALD(REG_ITMP3, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3604 disp = dseg_addaddress(cd, asm_handle_exception);
3605 M_ALD(REG_ITMP3, REG_PV, disp);
3611 /* generate ICMD_CHECKEXCEPTION stubs */
3615 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3616 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3617 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3619 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3623 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3625 (u1 *) mcodeptr - cd->mcodebase);
3629 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3631 if (xcodeptr != NULL) {
3632 disp = xcodeptr - mcodeptr - 1;
3636 xcodeptr = mcodeptr;
3638 M_MOV(REG_PV, rd->argintregs[0]);
3639 M_MOV(REG_SP, rd->argintregs[1]);
3640 M_ALD(rd->argintregs[2],
3641 REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3642 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3644 M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3645 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3647 disp = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
3648 M_ALD(REG_ITMP1, REG_PV, disp);
3651 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3653 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3654 M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3656 disp = dseg_addaddress(cd, asm_handle_exception);
3657 M_ALD(REG_ITMP3, REG_PV, disp);
3663 /* generate patcher stub call code */
3670 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3671 /* check code segment size */
3675 /* Get machine code which is patched back in later. The call is */
3676 /* 1 instruction word long. */
3678 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3681 /* patch in the call to call the following code (done at compile */
3684 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3685 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3687 M_BL(tmpmcodeptr - (xcodeptr + 1));
3689 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3691 /* create stack frame - keep stack 16-byte aligned */
3693 M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
3695 /* move return address onto stack */
3698 M_AST(REG_ITMP3, REG_SP, 4 * 4);
3700 /* move pointer to java_objectheader onto stack */
3702 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3703 /* order reversed because of data segment layout */
3705 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3706 disp = dseg_addaddress(cd, NULL); /* vftbl */
3708 if (disp >= -32768) {
3709 M_LDA(REG_ITMP3, REG_PV, disp);
3711 M_LDAH(REG_ITMP3, REG_PV, (disp >> 16));
3712 M_LDA(REG_ITMP3, REG_ITMP3, disp);
3714 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3717 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3720 /* move machine code onto stack */
3722 disp = dseg_adds4(cd, mcode);
3723 if (disp >= -32768) {
3724 M_ILD(REG_ITMP3, REG_PV, disp);
3726 M_LDAH(REG_ITMP3, REG_PV, (disp >> 16));
3727 M_ILD(REG_ITMP3, REG_ITMP3, disp);
3729 M_IST(REG_ITMP3, REG_SP, 2 * 4);
3731 /* move class/method/field reference onto stack */
3733 disp = dseg_addaddress(cd, pref->ref);
3734 if (disp >= -32768) {
3735 M_ALD(REG_ITMP3, REG_PV, disp);
3737 M_LDAH(REG_ITMP3, REG_PV, (disp >> 16));
3738 M_ALD(REG_ITMP3, REG_ITMP3, disp);
3740 M_AST(REG_ITMP3, REG_SP, 1 * 4);
3742 /* move patcher function pointer onto stack */
3744 disp = dseg_addaddress(cd, pref->patcher);
3745 if (disp >= -32768) {
3746 M_ALD(REG_ITMP3, REG_PV, disp);
3748 M_LDAH(REG_ITMP3, REG_PV, (disp >> 16));
3749 M_ALD(REG_ITMP3, REG_ITMP3, disp);
3751 M_AST(REG_ITMP3, REG_SP, 0 * 4);
3753 disp = dseg_addaddress(cd, asm_wrapper_patcher);
3754 if (disp >= -32768) {
3755 M_ALD(REG_ITMP3, REG_PV, disp);
3757 M_LDAH(REG_ITMP3, REG_PV, (disp >> 16));
3758 M_ALD(REG_ITMP3, REG_ITMP3, disp);
3767 codegen_finish(m, cd, (ptrint) ((u1 *) mcodeptr - cd->mcodebase));
3769 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3773 /* createcompilerstub **********************************************************
3775 Creates a stub routine which calls the compiler.
3777 *******************************************************************************/
3779 #define COMPSTUBSIZE 6
3781 functionptr createcompilerstub(methodinfo *m)
3783 s4 *s = CNEW(s4, COMPSTUBSIZE); /* memory to hold the stub */
3784 s4 *mcodeptr = s; /* code generation pointer */
3786 M_LDA(REG_ITMP1, REG_PV, 4*4);
3787 M_ALD(REG_PV, REG_PV, 5*4);
3791 s[4] = (s4) m; /* literals to be adressed */
3792 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3794 asm_cacheflush((void *) s, (u1 *) mcodeptr - (u1 *) s);
3796 #if defined(STATISTICS)
3798 count_cstub_len += COMPSTUBSIZE * 4;
3801 return (functionptr) (ptrint) s;
3805 /* createnativestub ************************************************************
3807 Creates a stub routine which calls a native method.
3809 *******************************************************************************/
3811 functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
3812 registerdata *rd, methoddesc *nmd)
3814 s4 *mcodeptr; /* code generation pointer */
3815 s4 stackframesize; /* size of stackframe if needed */
3819 s4 i, j; /* count variables */
3823 /* set some variables */
3826 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3828 /* calculate stackframe size */
3831 sizeof(stackframeinfo) / SIZEOF_VOID_P + /* native stackinfo */
3832 4 + /* 4 stackframeinfo arguments (darwin)*/
3833 nmd->paramcount * 2 + /* assume all arguments are doubles */
3836 stackframesize = (stackframesize + 3) & ~3; /* keep stack 16-byte aligned */
3839 /* create method header */
3841 (void) dseg_addaddress(cd, m); /* MethodPointer */
3842 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
3843 (void) dseg_adds4(cd, 0); /* IsSync */
3844 (void) dseg_adds4(cd, 0); /* IsLeaf */
3845 (void) dseg_adds4(cd, 0); /* IntSave */
3846 (void) dseg_adds4(cd, 0); /* FltSave */
3847 (void) dseg_addlinenumbertablesize(cd);
3848 (void) dseg_adds4(cd, 0); /* ExTableSize */
3851 /* initialize mcode variables */
3853 mcodeptr = (s4 *) cd->mcodebase;
3854 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
3860 M_AST(REG_ITMP1, REG_SP, LA_LR_OFFSET);
3861 M_STWU(REG_SP, REG_SP, -(stackframesize * 4));
3864 /* if function is static, check for initialized */
3866 if ((m->flags & ACC_STATIC) && !m->class->initialized) {
3867 codegen_addpatchref(cd, mcodeptr, PATCHER_clinit, m->class);
3869 if (opt_showdisassemble)
3874 /* parent_argbase == stackframesize * 4 */
3875 mcodeptr = codegen_trace_args(m, cd, rd, mcodeptr, stackframesize * 4 ,
3880 /* save integer and float argument registers */
3882 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
3883 t = md->paramtypes[i].type;
3885 if (IS_INT_LNG_TYPE(t)) {
3886 s1 = md->params[i].regoff;
3887 if (IS_2_WORD_TYPE(t)) {
3888 M_IST(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3889 M_IST(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3891 M_IST(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3896 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3897 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3898 s1 = md->params[i].regoff;
3899 M_DST(rd->argfltregs[s1], REG_SP, LA_SIZE + 4 * 4 + j++ * 8);
3903 /* create native stack info */
3905 M_AADD_IMM(REG_SP, stackframesize * 4 - sizeof(stackframeinfo),
3907 M_MOV(REG_PV, rd->argintregs[1]);
3908 M_AADD_IMM(REG_SP, stackframesize * 4, rd->argintregs[2]);
3909 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 4 + LA_LR_OFFSET);
3910 off = dseg_addaddress(cd, stacktrace_create_native_stackframeinfo);
3911 M_ALD(REG_ITMP1, REG_PV, off);
3915 /* restore integer and float argument registers */
3917 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
3918 t = md->paramtypes[i].type;
3920 if (IS_INT_LNG_TYPE(t)) {
3921 s1 = md->params[i].regoff;
3923 if (IS_2_WORD_TYPE(t)) {
3924 M_ILD(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3925 M_ILD(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3927 M_ILD(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j++ * 4);
3932 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3933 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3934 s1 = md->params[i].regoff;
3935 M_DLD(rd->argfltregs[i], REG_SP, LA_SIZE + 4 * 4 + j++ * 8);
3940 /* copy or spill arguments to new locations */
3942 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3943 t = md->paramtypes[i].type;
3945 if (IS_INT_LNG_TYPE(t)) {
3946 if (!md->params[i].inmemory) {
3947 if (IS_2_WORD_TYPE(t))
3949 rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
3950 rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
3952 s1 = rd->argintregs[md->params[i].regoff];
3954 if (!nmd->params[j].inmemory) {
3955 if (IS_2_WORD_TYPE(t))
3957 rd->argintregs[GET_LOW_REG(nmd->params[j].regoff)],
3958 rd->argintregs[GET_HIGH_REG(nmd->params[j].regoff)]);
3960 s2 = rd->argintregs[nmd->params[j].regoff];
3961 M_TINTMOVE(t, s1, s2);
3964 s2 = nmd->params[j].regoff;
3965 if (IS_2_WORD_TYPE(t)) {
3966 M_IST(GET_HIGH_REG(s1), REG_SP, s2 * 4);
3967 M_IST(GET_LOW_REG(s1), REG_SP, s2 * 4 + 4);
3969 M_IST(s1, REG_SP, s2 * 4);
3974 s1 = md->params[i].regoff + stackframesize;
3975 s2 = nmd->params[j].regoff;
3977 M_ILD(REG_ITMP1, REG_SP, s1 * 4);
3978 M_IST(REG_ITMP1, REG_SP, s2 * 4);
3979 if (IS_2_WORD_TYPE(t)) {
3980 M_ILD(REG_ITMP1, REG_SP, s1 * 4 + 4);
3981 M_IST(REG_ITMP1, REG_SP, s2 * 4 + 4);
3986 /* We only copy spilled float arguments, as the float argument */
3987 /* registers keep unchanged. */
3989 if (md->params[i].inmemory) {
3990 s1 = md->params[i].regoff + stackframesize;
3991 s2 = nmd->params[j].regoff;
3993 if (IS_2_WORD_TYPE(t)) {
3994 M_DLD(REG_FTMP1, REG_SP, s1 * 4);
3995 M_DST(REG_FTMP1, REG_SP, s2 * 4);
3998 M_FLD(REG_FTMP1, REG_SP, s1 * 4);
3999 M_FST(REG_FTMP1, REG_SP, s2 * 4);
4005 /* put class into second argument register */
4007 if (m->flags & ACC_STATIC) {
4008 off = dseg_addaddress(cd, m->class);
4009 M_ALD(rd->argintregs[1], REG_PV, off);
4012 /* put env into first argument register */
4014 off = dseg_addaddress(cd, &env);
4015 M_ALD(rd->argintregs[0], REG_PV, off);
4017 /* generate the actual native call */
4019 #if !defined(ENABLE_STATICVM)
4021 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m);
4023 if (opt_showdisassemble)
4028 off = dseg_addaddress(cd, f);
4029 M_ALD(REG_PV, REG_PV, off);
4032 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4034 M_LDA(REG_PV, REG_ITMP1, -disp); /* recompute pv from ra */
4037 /* remove native stackframe info */
4039 switch (md->returntype.type) {
4041 M_IST(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);
4045 M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
4048 M_FST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4051 M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4055 M_AADD_IMM(REG_SP, stackframesize * 4 - sizeof(stackframeinfo),
4057 off = dseg_addaddress(cd, stacktrace_remove_stackframeinfo);
4058 M_ALD(REG_ITMP1, REG_PV, off);
4062 switch (md->returntype.type) {
4064 M_ILD(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);
4068 M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
4071 M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4074 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4079 /* print call trace */
4082 M_LDA(REG_SP, REG_SP, -(LA_SIZE + ((1 + 2 + 2 + 1) + 2 + 2) * 4));
4083 M_IST(REG_RESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 0) * 4);
4084 M_IST(REG_RESULT2, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 1) * 4);
4085 M_DST(REG_FRESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2) * 4);
4087 /* keep this order */
4088 switch (md->returntype.type) {
4091 #if defined(__DARWIN__)
4092 M_MOV(REG_RESULT, rd->argintregs[2]);
4093 M_CLR(rd->argintregs[1]);
4095 M_MOV(REG_RESULT, rd->argintregs[3]);
4096 M_CLR(rd->argintregs[2]);
4101 #if defined(__DARWIN__)
4102 M_MOV(REG_RESULT2, rd->argintregs[2]);
4103 M_MOV(REG_RESULT, rd->argintregs[1]);
4105 M_MOV(REG_RESULT2, rd->argintregs[3]);
4106 M_MOV(REG_RESULT, rd->argintregs[2]);
4111 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
4112 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
4113 off = dseg_addaddress(cd, m);
4114 M_ALD(rd->argintregs[0], REG_PV, off);
4116 off = dseg_addaddress(cd, builtin_displaymethodstop);
4117 M_ALD(REG_ITMP2, REG_PV, off);
4121 M_ILD(REG_RESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 0) * 4);
4122 M_ILD(REG_RESULT2, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 1) * 4);
4123 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2) * 4);
4124 M_LDA(REG_SP, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2 + 2) * 4);
4127 /* check for exception */
4129 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4130 switch (md->returntype.type) {
4132 M_IST(REG_RESULT2, REG_SP, (stackframesize - 1) * 4);
4136 M_IST(REG_RESULT, REG_SP, (stackframesize - 2) * 4);
4139 M_FST(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4142 M_DST(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4146 off = dseg_addaddress(cd, builtin_get_exceptionptrptr);
4147 M_ALD(REG_ITMP1, REG_PV, off);
4150 M_MOV(REG_RESULT, REG_ITMP2);
4152 switch (md->returntype.type) {
4154 M_ILD(REG_RESULT2, REG_SP, (stackframesize - 1) * 4);
4158 M_ILD(REG_RESULT, REG_SP, (stackframesize - 2) * 4);
4161 M_FLD(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4164 M_DLD(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4168 off = dseg_addaddress(cd, &_exceptionptr)
4169 M_ALD(REG_ITMP2, REG_PV, off);
4171 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);/* load exception into reg. itmp1 */
4172 M_TST(REG_ITMP1_XPTR);
4173 M_BNE(4); /* if no exception then return */
4175 M_ALD(REG_ITMP1, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra */
4177 M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe */
4181 /* handle exception */
4184 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
4186 M_ALD(REG_ITMP2, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra */
4189 M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe */
4191 M_IADD_IMM(REG_ITMP2, -4, REG_ITMP2_XPC); /* fault address */
4193 off = dseg_addaddress(cd, asm_handle_nat_exception);
4194 M_ALD(REG_ITMP3, REG_PV, off);
4198 /* generate patcher stub call code */
4206 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4207 /* Get machine code which is patched back in later. The call is */
4208 /* 1 instruction word long. */
4210 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4211 mcode = (u4) *xcodeptr;
4213 /* patch in the call to call the following code (done at compile */
4216 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4217 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4219 M_BL(tmpmcodeptr - (xcodeptr + 1));
4221 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4223 /* create stack frame - keep stack 16-byte aligned */
4225 M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
4227 /* move return address onto stack */
4230 M_AST(REG_ITMP3, REG_SP, 4 * 4);
4232 /* move pointer to java_objectheader onto stack */
4234 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4235 /* order reversed because of data segment layout */
4237 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4238 off = dseg_addaddress(cd, NULL); /* vftbl */
4240 M_LDA(REG_ITMP3, REG_PV, off);
4241 M_AST(REG_ITMP3, REG_SP, 3 * 4);
4244 M_AST(REG_ITMP3, REG_SP, 3 * 4);
4247 /* move machine code onto stack */
4249 off = dseg_adds4(cd, mcode);
4250 M_ILD(REG_ITMP3, REG_PV, off);
4251 M_IST(REG_ITMP3, REG_SP, 2 * 4);
4253 /* move class/method/field reference onto stack */
4255 off = dseg_addaddress(cd, pref->ref);
4256 M_ALD(REG_ITMP3, REG_PV, off);
4257 M_AST(REG_ITMP3, REG_SP, 1 * 4);
4259 /* move patcher function pointer onto stack */
4261 off = dseg_addaddress(cd, pref->patcher);
4262 M_ALD(REG_ITMP3, REG_PV, off);
4263 M_AST(REG_ITMP3, REG_SP, 0 * 4);
4265 off = dseg_addaddress(cd, asm_wrapper_patcher);
4266 M_ALD(REG_ITMP3, REG_PV, off);
4272 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4274 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4276 return m->entrypoint;
4280 s4 *codegen_trace_args(methodinfo *m, codegendata *cd, registerdata *rd,
4281 s4 *mcodeptr, s4 parentargs_base, bool nativestub)
4292 /* Build up Stackframe for builtin_trace_args call (a multiple of 16) */
4294 /* LA + TRACE_ARGS_NUM u8 args + methodinfo + LR */
4295 /* LA_SIZE(=6*4) + 8*8 + 4 + 4 + 0(Padding) */
4296 /* 6 * 4 + 8 * 8 + 2 * 4 = 12 * 8 = 6 * 16 */
4298 /* LA + (TRACE_ARGS_NUM - INT_ARG_CNT/2) u8 args + methodinfo */
4299 /* + INT_ARG_CNT * 4 ( save integer registers) + LR + 8 + 8 (Padding) */
4300 /* LA_SIZE(=2*4) + 4 * 8 + 4 + 8 * 4 + 4 + 8 */
4301 /* 2 * 4 + 4 * 8 + 10 * 4 + 1 * 8 + 8= 12 * 8 = 6 * 16 */
4303 /* in nativestubs no Place to save the LR (Link Register) would be needed */
4304 /* but since the stack frame has to be aligned the 4 Bytes would have to */
4305 /* be padded again */
4307 #if defined(__DARWIN__)
4308 stack_size = LA_SIZE + (TRACE_ARGS_NUM + 1) * 8;
4310 stack_size = 6 * 16;
4312 M_LDA(REG_SP, REG_SP, -stack_size);
4316 M_IST(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
4318 M_CLR(REG_ITMP1); /* clear help register */
4320 /* save up to TRACE_ARGS_NUM arguments into the reserved stack space */
4321 #if defined(__DARWIN__)
4322 /* Copy Params starting from first to Stack */
4323 /* since TRACE_ARGS == INT_ARG_CNT all used integer argument regs */
4327 /* Copy Params starting from fifth to Stack (INT_ARG_CNT/2) are in */
4328 /* integer argument regs */
4329 /* all integer argument registers have to be saved */
4330 for (p = 0; p < 8; p++) {
4331 d = rd->argintregs[p];
4332 /* save integer argument registers */
4333 M_IST(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
4337 stack_off = LA_SIZE;
4338 for (; p < md->paramcount && p < TRACE_ARGS_NUM; p++, stack_off += 8) {
4339 t = md->paramtypes[p].type;
4340 if (IS_INT_LNG_TYPE(t)) {
4341 if (!md->params[p].inmemory) { /* Param in Arg Reg */
4342 if (IS_2_WORD_TYPE(t)) {
4343 M_IST(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
4344 , REG_SP, stack_off);
4345 M_IST(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
4346 , REG_SP, stack_off + 4);
4348 M_IST(REG_ITMP1, REG_SP, stack_off);
4349 M_IST(rd->argintregs[md->params[p].regoff]
4350 , REG_SP, stack_off + 4);
4352 } else { /* Param on Stack */
4353 s1 = (md->params[p].regoff + parentargs_base) * 4
4355 if (IS_2_WORD_TYPE(t)) {
4356 M_ILD(REG_ITMP2, REG_SP, s1);
4357 M_IST(REG_ITMP2, REG_SP, stack_off);
4358 M_ILD(REG_ITMP2, REG_SP, s1 + 4);
4359 M_IST(REG_ITMP2, REG_SP, stack_off + 4);
4361 M_IST(REG_ITMP1, REG_SP, stack_off);
4362 M_ILD(REG_ITMP2, REG_SP, s1);
4363 M_IST(REG_ITMP2, REG_SP, stack_off + 4);
4366 } else { /* IS_FLT_DBL_TYPE(t) */
4367 if (!md->params[p].inmemory) { /* in Arg Reg */
4368 s1 = rd->argfltregs[md->params[p].regoff];
4369 if (!IS_2_WORD_TYPE(t)) {
4370 M_IST(REG_ITMP1, REG_SP, stack_off);
4371 M_FST(s1, REG_SP, stack_off + 4);
4373 M_DST(s1, REG_SP, stack_off);
4375 } else { /* on Stack */
4376 /* this should not happen */
4381 /* load first 4 (==INT_ARG_CNT/2) arguments into integer registers */
4382 #if defined(__DARWIN__)
4383 for (p = 0; p < 8; p++) {
4384 d = rd->argintregs[p];
4385 M_ILD(d, REG_SP, LA_SIZE + p * 4);
4389 /* Set integer and float argument registers vor trace_args call */
4390 /* offset to saved integer argument registers */
4391 stack_off = LA_SIZE + 4 * 8 + 4;
4392 for (p = 0; (p < 4) && (p < md->paramcount); p++) {
4393 t = md->paramtypes[p].type;
4394 if (IS_INT_LNG_TYPE(t)) {
4395 /* "stretch" int types */
4396 if (!IS_2_WORD_TYPE(t)) {
4397 M_CLR(rd->argintregs[2 * p]);
4398 M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off);
4401 M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off + 4);
4402 M_ILD(rd->argintregs[2 * p], REG_SP,stack_off);
4405 } else { /* Float/Dbl */
4406 if (!md->params[p].inmemory) { /* Param in Arg Reg */
4407 /* use reserved Place on Stack (sp + 5 * 16) to copy */
4408 /* float/double arg reg to int reg */
4409 s1 = rd->argfltregs[md->params[p].regoff];
4410 if (!IS_2_WORD_TYPE(t)) {
4411 M_FST(s1, REG_SP, 5 * 16);
4412 M_ILD(rd->argintregs[2 * p + 1], REG_SP, 5 * 16);
4413 M_CLR(rd->argintregs[2 * p]);
4415 M_DST(s1, REG_SP, 5 * 16);
4416 M_ILD(rd->argintregs[2 * p + 1], REG_SP, 5 * 16 + 4);
4417 M_ILD(rd->argintregs[2 * p], REG_SP, 5 * 16);
4424 /* put methodinfo pointer on Stackframe */
4425 p = dseg_addaddress(cd, m);
4426 M_ALD(REG_ITMP1, REG_PV, p);
4427 #if defined(__DARWIN__)
4428 M_AST(REG_ITMP1, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8);
4430 M_AST(REG_ITMP1, REG_SP, LA_SIZE + 4 * 8);
4432 p = dseg_addaddress(cd, (void *) builtin_trace_args);
4433 M_ALD(REG_ITMP2, REG_PV, p);
4437 #if defined(__DARWIN__)
4438 /* restore integer argument registers from the reserved stack space */
4440 stack_off = LA_SIZE;
4441 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM;
4442 p++, stack_off += 8) {
4443 t = md->paramtypes[p].type;
4445 if (IS_INT_LNG_TYPE(t)) {
4446 if (!md->params[p].inmemory) {
4447 if (IS_2_WORD_TYPE(t)) {
4448 M_ILD(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
4449 , REG_SP, stack_off);
4450 M_ILD(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
4451 , REG_SP, stack_off + 4);
4453 M_ILD(rd->argintregs[md->params[p].regoff]
4454 , REG_SP, stack_off + 4);
4461 for (p = 0; p < 8; p++) {
4462 d = rd->argintregs[p];
4463 /* save integer argument registers */
4464 M_ILD(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
4469 M_ILD(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
4471 M_LDA(REG_SP, REG_SP, stack_size);
4478 * These are local overrides for various environment variables in Emacs.
4479 * Please do not remove this and leave it at the end of the file, where
4480 * Emacs will automagically detect them.
4481 * ---------------------------------------------------------------------
4484 * indent-tabs-mode: t