1 /* src/vm/jit/mips/codegen.c - machine code generator for MIPS
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 Contains the codegenerator for an MIPS (R4000 or higher) processor.
34 This module generates MIPS machine code for a sequence of
35 intermediate code commands (ICMDs).
37 $Id: codegen.c 3717 2005-11-19 01:59:07Z edwin $
52 #include "vm/jit/mips/arch.h"
53 #include "vm/jit/mips/codegen.h"
55 #include "cacao/cacao.h"
56 #include "native/native.h"
57 #include "vm/builtin.h"
58 #include "vm/stringlocal.h"
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/codegen.inc"
61 #include "vm/jit/jit.h"
64 # include "vm/jit/lsra.h"
65 # include "vm/jit/lsra.inc"
68 #include "vm/jit/patcher.h"
69 #include "vm/jit/reg.h"
70 #include "vm/jit/reg.inc"
73 /* codegen *********************************************************************
75 Generates machine code.
77 *******************************************************************************/
79 bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
81 s4 len, s1, s2, s3, d, disp;
91 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
92 builtintable_entry *bte;
99 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
101 /* space to save used callee saved registers */
103 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
104 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
106 parentargs_base = rd->memuse + savedregs_num;
108 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
109 if (checksync && (m->flags & ACC_SYNCHRONIZED))
113 /* adjust frame size for 16 byte alignment */
115 if (parentargs_base & 1)
118 /* create method header */
120 #if SIZEOF_VOID_P == 4
121 (void) dseg_addaddress(cd, m); /* Filler */
123 (void) dseg_addaddress(cd, m); /* MethodPointer */
124 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
126 #if defined(USE_THREADS)
127 /* IsSync contains the offset relative to the stack pointer for the
128 argument of monitor_exit used in the exception handler. Since the
129 offset could be zero and give a wrong meaning of the flag it is
133 if (checksync && (m->flags & ACC_SYNCHRONIZED))
134 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
137 (void) dseg_adds4(cd, 0); /* IsSync */
139 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
140 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
141 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
142 dseg_addlinenumbertablesize(cd);
143 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
145 /* create exception table */
147 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
148 dseg_addtarget(cd, ex->start);
149 dseg_addtarget(cd, ex->end);
150 dseg_addtarget(cd, ex->handler);
151 (void) dseg_addaddress(cd, ex->catchtype.cls);
154 /* initialize mcode variables */
156 mcodeptr = (s4 *) cd->mcodebase;
157 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
158 MCODECHECK(128 + m->paramcount);
160 /* initialize the last patcher pointer */
162 cd->lastmcodeptr = (u1 *) mcodeptr;
164 /* create stack frame (if necessary) */
167 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
169 /* save return address and used callee saved registers */
172 if (!m->isleafmethod) {
173 p--; M_AST(REG_RA, REG_SP, p * 8);
175 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
176 p--; M_AST(rd->savintregs[i], REG_SP, p * 8);
178 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
179 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
182 /* take arguments out of register or stack frame */
186 for (p = 0, l = 0; p < md->paramcount; p++) {
187 t = md->paramtypes[p].type;
188 var = &(rd->locals[l][t]);
190 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
194 s1 = md->params[p].regoff;
195 if (IS_INT_LNG_TYPE(t)) { /* integer args */
196 if (!md->params[p].inmemory) { /* register arguments */
197 s2 = rd->argintregs[s1];
198 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
199 M_INTMOVE(s2, var->regoff);
200 } else { /* reg arg -> spilled */
201 M_LST(s2, REG_SP, var->regoff * 8);
204 } else { /* stack arguments */
205 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
206 M_LLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
207 } else { /* stack arg -> spilled */
208 var->regoff = parentargs_base + s1;
212 } else { /* floating args */
213 if (!md->params[p].inmemory) { /* register arguments */
214 s2 = rd->argfltregs[s1];
215 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
216 M_TFLTMOVE(var->type, s2, var->regoff);
217 } else { /* reg arg -> spilled */
218 M_DST(s2, REG_SP, var->regoff * 8);
221 } else { /* stack arguments */
222 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
223 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
224 } else { /* stack-arg -> spilled */
225 var->regoff = parentargs_base + s1;
231 /* call monitorenter function */
233 #if defined(USE_THREADS)
234 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
235 /* stack offset for monitor argument */
240 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
242 for (p = 0; p < INT_ARG_CNT; p++)
243 M_LST(rd->argintregs[p], REG_SP, p * 8);
245 for (p = 0; p < FLT_ARG_CNT; p++)
246 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
248 s1 += INT_ARG_CNT + FLT_ARG_CNT;
251 /* decide which monitor enter function to call */
253 if (m->flags & ACC_STATIC) {
254 p = dseg_addaddress(cd, m->class);
255 M_ALD(REG_ITMP1, REG_PV, p);
256 M_AST(REG_ITMP1, REG_SP, s1 * 8);
257 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
258 M_ALD(REG_ITMP3, REG_PV, p);
259 M_JSR(REG_RA, REG_ITMP3);
260 M_INTMOVE(REG_ITMP1, rd->argintregs[0]); /* branch delay */
263 M_BEQZ(rd->argintregs[0], 0);
264 codegen_addxnullrefs(cd, mcodeptr);
265 p = dseg_addaddress(cd, BUILTIN_monitorenter);
266 M_ALD(REG_ITMP3, REG_PV, p);
267 M_JSR(REG_RA, REG_ITMP3);
268 M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* br delay */
272 for (p = 0; p < INT_ARG_CNT; p++)
273 M_LLD(rd->argintregs[p], REG_SP, p * 8);
275 for (p = 0; p < FLT_ARG_CNT; p++)
276 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
279 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
284 /* copy argument registers to stack and call trace function */
287 M_LDA(REG_SP, REG_SP, -(2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
288 M_AST(REG_RA, REG_SP, 1 * 8);
290 /* save integer argument registers */
292 for (p = 0; p < md->paramcount && p < INT_ARG_CNT; p++)
293 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
295 /* save and copy float arguments into integer registers */
297 for (p = 0; p < md->paramcount && p < FLT_ARG_CNT; p++) {
298 t = md->paramtypes[p].type;
300 if (IS_FLT_DBL_TYPE(t)) {
301 if (IS_2_WORD_TYPE(t)) {
302 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
303 M_LLD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
306 M_FST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
307 M_ILD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
311 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
315 /* save temporary registers for leaf methods */
317 if (m->isleafmethod) {
318 for (p = 0; p < INT_TMP_CNT; p++)
319 M_LST(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
321 for (p = 0; p < FLT_TMP_CNT; p++)
322 M_DST(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
325 p = dseg_addaddress(cd, m);
326 M_ALD(REG_ITMP1, REG_PV, p);
327 M_AST(REG_ITMP1, REG_SP, 0 * 8);
328 disp = dseg_addaddress(cd, (void *) builtin_trace_args);
329 M_ALD(REG_ITMP3, REG_PV, disp);
330 M_JSR(REG_RA, REG_ITMP3);
333 M_ALD(REG_RA, REG_SP, 1 * 8);
335 /* restore integer argument registers */
337 for (p = 0; p < md->paramcount && p < INT_ARG_CNT; p++)
338 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
340 /* restore float argument registers */
342 for (p = 0; p < md->paramcount && p < FLT_ARG_CNT; p++) {
343 t = md->paramtypes[p].type;
345 if (IS_FLT_DBL_TYPE(t)) {
346 if (IS_2_WORD_TYPE(t)) {
347 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
350 M_FLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
354 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
358 /* restore temporary registers for leaf methods */
360 if (m->isleafmethod) {
361 for (p = 0; p < INT_TMP_CNT; p++)
362 M_LLD(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
364 for (p = 0; p < FLT_TMP_CNT; p++)
365 M_DLD(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
368 M_LDA(REG_SP, REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
373 /* end of header generation */
375 /* walk through all basic blocks */
377 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
379 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
381 if (bptr->flags >= BBREACHED) {
383 /* branch resolving */
386 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
387 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
393 /* copy interface registers to their destination */
400 while (src != NULL) {
402 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
403 /* d = reg_of_var(m, src, REG_ITMP1); */
404 if (!(src->flags & INMEMORY))
408 M_INTMOVE(REG_ITMP1, d);
409 store_reg_to_var_int(src, d);
415 while (src != NULL) {
417 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
418 d = reg_of_var(rd, src, REG_ITMP1);
419 M_INTMOVE(REG_ITMP1, d);
420 store_reg_to_var_int(src, d);
423 d = reg_of_var(rd, src, REG_IFTMP);
424 if ((src->varkind != STACKVAR)) {
426 if (IS_FLT_DBL_TYPE(s2)) {
427 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
428 s1 = rd->interfaces[len][s2].regoff;
429 M_TFLTMOVE(s2, s1, d);
432 M_DLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
434 store_reg_to_var_flt(src, d);
437 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
438 s1 = rd->interfaces[len][s2].regoff;
442 M_LLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
444 store_reg_to_var_int(src, d);
453 /* walk through all instructions */
459 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
460 if (iptr->line != currentline) {
461 dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
462 currentline = iptr->line;
465 MCODECHECK(64); /* an instruction usually needs < 64 words */
469 case ICMD_NOP: /* ... ==> ... */
472 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
474 var_to_reg_int(s1, src, REG_ITMP1);
476 codegen_addxnullrefs(cd, mcodeptr);
480 /* constant operations ************************************************/
482 case ICMD_ICONST: /* ... ==> ..., constant */
483 /* op1 = 0, val.i = constant */
485 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
486 ICONST(d, iptr->val.i);
487 store_reg_to_var_int(iptr->dst, d);
490 case ICMD_LCONST: /* ... ==> ..., constant */
491 /* op1 = 0, val.l = constant */
493 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
494 LCONST(d, iptr->val.l);
495 store_reg_to_var_int(iptr->dst, d);
498 case ICMD_FCONST: /* ... ==> ..., constant */
499 /* op1 = 0, val.f = constant */
501 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
502 disp = dseg_addfloat(cd, iptr->val.f);
503 M_FLD(d, REG_PV, disp);
504 store_reg_to_var_flt(iptr->dst, d);
507 case ICMD_DCONST: /* ... ==> ..., constant */
508 /* op1 = 0, val.d = constant */
510 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
511 disp = dseg_adddouble(cd, iptr->val.d);
512 M_DLD(d, REG_PV, disp);
513 store_reg_to_var_flt (iptr->dst, d);
516 case ICMD_ACONST: /* ... ==> ..., constant */
517 /* op1 = 0, val.a = constant */
519 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
521 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
522 disp = dseg_addaddress(cd, iptr->val.a);
524 codegen_addpatchref(cd, mcodeptr,
526 (unresolved_class *) iptr->target, disp);
528 if (opt_showdisassemble) {
532 M_ALD(d, REG_PV, disp);
535 if (iptr->val.a == NULL) {
536 M_INTMOVE(REG_ZERO, d);
538 disp = dseg_addaddress(cd, iptr->val.a);
539 M_ALD(d, REG_PV, disp);
542 store_reg_to_var_int(iptr->dst, d);
546 /* load/store operations **********************************************/
548 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
549 case ICMD_LLOAD: /* op1 = local variable */
552 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
553 if ((iptr->dst->varkind == LOCALVAR) &&
554 (iptr->dst->varnum == iptr->op1))
556 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
557 if (var->flags & INMEMORY) {
558 M_LLD(d, REG_SP, 8 * var->regoff);
560 M_INTMOVE(var->regoff,d);
562 store_reg_to_var_int(iptr->dst, d);
565 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
566 case ICMD_DLOAD: /* op1 = local variable */
568 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
569 if ((iptr->dst->varkind == LOCALVAR) &&
570 (iptr->dst->varnum == iptr->op1))
572 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
574 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
575 if (var->flags & INMEMORY) {
576 M_CCFLD(var->type, t2, d, REG_SP, 8 * var->regoff);
578 M_CCFLTMOVE(var->type, t2, var->regoff, d);
581 store_reg_to_var_flt(iptr->dst, d);
585 case ICMD_ISTORE: /* ..., value ==> ... */
586 case ICMD_LSTORE: /* op1 = local variable */
589 if ((src->varkind == LOCALVAR) &&
590 (src->varnum == iptr->op1))
592 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
593 if (var->flags & INMEMORY) {
594 var_to_reg_int(s1, src, REG_ITMP1);
595 M_LST(s1, REG_SP, 8 * var->regoff);
598 var_to_reg_int(s1, src, var->regoff);
599 M_INTMOVE(s1, var->regoff);
603 case ICMD_FSTORE: /* ..., value ==> ... */
604 case ICMD_DSTORE: /* op1 = local variable */
606 if ((src->varkind == LOCALVAR) &&
607 (src->varnum == iptr->op1))
609 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
611 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
612 if (var->flags & INMEMORY) {
613 var_to_reg_flt(s1, src, REG_FTMP1);
614 M_CCFST(t1, var->type, s1, REG_SP, 8 * var->regoff);
617 var_to_reg_flt(s1, src, var->regoff);
618 M_CCFLTMOVE(t1, var->type, s1, var->regoff);
624 /* pop/dup/swap operations ********************************************/
626 /* attention: double and longs are only one entry in CACAO ICMDs */
628 case ICMD_POP: /* ..., value ==> ... */
629 case ICMD_POP2: /* ..., value, value ==> ... */
632 case ICMD_DUP: /* ..., a ==> ..., a, a */
633 M_COPY(src, iptr->dst);
636 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
638 M_COPY(src, iptr->dst);
639 M_COPY(src->prev, iptr->dst->prev);
640 M_COPY(iptr->dst, iptr->dst->prev->prev);
643 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
645 M_COPY(src, iptr->dst);
646 M_COPY(src->prev, iptr->dst->prev);
647 M_COPY(src->prev->prev, iptr->dst->prev->prev);
648 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
651 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
653 M_COPY(src, iptr->dst);
654 M_COPY(src->prev, iptr->dst->prev);
657 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
659 M_COPY(src, iptr->dst);
660 M_COPY(src->prev, iptr->dst->prev);
661 M_COPY(src->prev->prev, iptr->dst->prev->prev);
662 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
663 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
666 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
668 M_COPY(src, iptr->dst);
669 M_COPY(src->prev, iptr->dst->prev);
670 M_COPY(src->prev->prev, iptr->dst->prev->prev);
671 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
672 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
673 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
676 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
678 M_COPY(src, iptr->dst->prev);
679 M_COPY(src->prev, iptr->dst);
683 /* integer operations *************************************************/
685 case ICMD_INEG: /* ..., value ==> ..., - value */
687 var_to_reg_int(s1, src, REG_ITMP1);
688 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
689 M_ISUB(REG_ZERO, s1, d);
690 store_reg_to_var_int(iptr->dst, d);
693 case ICMD_LNEG: /* ..., value ==> ..., - value */
695 var_to_reg_int(s1, src, REG_ITMP1);
696 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
697 M_LSUB(REG_ZERO, s1, d);
698 store_reg_to_var_int(iptr->dst, d);
701 case ICMD_I2L: /* ..., value ==> ..., value */
703 var_to_reg_int(s1, src, REG_ITMP1);
704 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
706 store_reg_to_var_int(iptr->dst, d);
709 case ICMD_L2I: /* ..., value ==> ..., value */
711 var_to_reg_int(s1, src, REG_ITMP1);
712 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
713 M_ISLL_IMM(s1, 0, d );
714 store_reg_to_var_int(iptr->dst, d);
717 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
719 var_to_reg_int(s1, src, REG_ITMP1);
720 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
721 M_LSLL_IMM(s1, 56, d);
722 M_LSRA_IMM( d, 56, d);
723 store_reg_to_var_int(iptr->dst, d);
726 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
728 var_to_reg_int(s1, src, REG_ITMP1);
729 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
731 store_reg_to_var_int(iptr->dst, d);
734 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
736 var_to_reg_int(s1, src, REG_ITMP1);
737 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
738 M_LSLL_IMM(s1, 48, d);
739 M_LSRA_IMM( d, 48, d);
740 store_reg_to_var_int(iptr->dst, d);
744 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
746 var_to_reg_int(s1, src->prev, REG_ITMP1);
747 var_to_reg_int(s2, src, REG_ITMP2);
748 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
750 store_reg_to_var_int(iptr->dst, d);
753 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
754 /* val.i = constant */
756 var_to_reg_int(s1, src, REG_ITMP1);
757 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
758 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
759 M_IADD_IMM(s1, iptr->val.i, d);
761 ICONST(REG_ITMP2, iptr->val.i);
762 M_IADD(s1, REG_ITMP2, d);
764 store_reg_to_var_int(iptr->dst, d);
767 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
769 var_to_reg_int(s1, src->prev, REG_ITMP1);
770 var_to_reg_int(s2, src, REG_ITMP2);
771 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
773 store_reg_to_var_int(iptr->dst, d);
776 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
777 /* val.l = constant */
779 var_to_reg_int(s1, src, REG_ITMP1);
780 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
781 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
782 M_LADD_IMM(s1, iptr->val.l, d);
784 LCONST(REG_ITMP2, iptr->val.l);
785 M_LADD(s1, REG_ITMP2, d);
787 store_reg_to_var_int(iptr->dst, d);
790 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
792 var_to_reg_int(s1, src->prev, REG_ITMP1);
793 var_to_reg_int(s2, src, REG_ITMP2);
794 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
796 store_reg_to_var_int(iptr->dst, d);
799 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
800 /* val.i = constant */
802 var_to_reg_int(s1, src, REG_ITMP1);
803 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
804 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
805 M_IADD_IMM(s1, -iptr->val.i, d);
807 ICONST(REG_ITMP2, iptr->val.i);
808 M_ISUB(s1, REG_ITMP2, d);
810 store_reg_to_var_int(iptr->dst, d);
813 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
815 var_to_reg_int(s1, src->prev, REG_ITMP1);
816 var_to_reg_int(s2, src, REG_ITMP2);
817 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
819 store_reg_to_var_int(iptr->dst, d);
822 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
823 /* val.l = constant */
825 var_to_reg_int(s1, src, REG_ITMP1);
826 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
827 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
828 M_LADD_IMM(s1, -iptr->val.l, d);
830 LCONST(REG_ITMP2, iptr->val.l);
831 M_LSUB(s1, REG_ITMP2, d);
833 store_reg_to_var_int(iptr->dst, d);
836 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
838 var_to_reg_int(s1, src->prev, REG_ITMP1);
839 var_to_reg_int(s2, src, REG_ITMP2);
840 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
845 store_reg_to_var_int(iptr->dst, d);
848 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
849 /* val.i = constant */
851 var_to_reg_int(s1, src, REG_ITMP1);
852 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
853 ICONST(REG_ITMP2, iptr->val.i);
854 M_IMUL(s1, REG_ITMP2);
858 store_reg_to_var_int(iptr->dst, d);
861 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
863 var_to_reg_int(s1, src->prev, REG_ITMP1);
864 var_to_reg_int(s2, src, REG_ITMP2);
865 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
870 store_reg_to_var_int(iptr->dst, d);
873 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
874 /* val.l = constant */
876 var_to_reg_int(s1, src, REG_ITMP1);
877 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
878 LCONST(REG_ITMP2, iptr->val.l);
879 M_LMUL(s1, REG_ITMP2);
883 store_reg_to_var_int(iptr->dst, d);
886 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
888 var_to_reg_int(s1, src->prev, REG_ITMP1);
889 var_to_reg_int(s2, src, REG_ITMP2);
890 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
896 store_reg_to_var_int(iptr->dst, d);
899 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
901 var_to_reg_int(s1, src->prev, REG_ITMP1);
902 var_to_reg_int(s2, src, REG_ITMP2);
903 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
909 store_reg_to_var_int(iptr->dst, d);
912 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
914 var_to_reg_int(s1, src->prev, REG_ITMP1);
915 var_to_reg_int(s2, src, REG_ITMP2);
916 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
922 store_reg_to_var_int(iptr->dst, d);
925 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
927 var_to_reg_int(s1, src->prev, REG_ITMP1);
928 var_to_reg_int(s2, src, REG_ITMP2);
929 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
935 store_reg_to_var_int(iptr->dst, d);
938 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
939 case ICMD_LDIVPOW2: /* val.i = constant */
941 var_to_reg_int(s1, src, REG_ITMP1);
942 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
943 M_LSRA_IMM(s1, 63, REG_ITMP2);
944 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
945 M_LADD(s1, REG_ITMP2, REG_ITMP2);
946 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
947 store_reg_to_var_int(iptr->dst, d);
950 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
952 var_to_reg_int(s1, src->prev, REG_ITMP1);
953 var_to_reg_int(s2, src, REG_ITMP2);
954 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
956 store_reg_to_var_int(iptr->dst, d);
959 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
960 /* val.i = constant */
962 var_to_reg_int(s1, src, REG_ITMP1);
963 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
964 M_ISLL_IMM(s1, iptr->val.i, d);
965 store_reg_to_var_int(iptr->dst, d);
968 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
970 var_to_reg_int(s1, src->prev, REG_ITMP1);
971 var_to_reg_int(s2, src, REG_ITMP2);
972 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
974 store_reg_to_var_int(iptr->dst, d);
977 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
978 /* val.i = constant */
980 var_to_reg_int(s1, src, REG_ITMP1);
981 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
982 M_ISRA_IMM(s1, iptr->val.i, d);
983 store_reg_to_var_int(iptr->dst, d);
986 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
988 var_to_reg_int(s1, src->prev, REG_ITMP1);
989 var_to_reg_int(s2, src, REG_ITMP2);
990 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
992 store_reg_to_var_int(iptr->dst, d);
995 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
996 /* val.i = constant */
998 var_to_reg_int(s1, src, REG_ITMP1);
999 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1000 M_ISRL_IMM(s1, iptr->val.i, d);
1001 store_reg_to_var_int(iptr->dst, d);
1004 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1006 var_to_reg_int(s1, src->prev, REG_ITMP1);
1007 var_to_reg_int(s2, src, REG_ITMP2);
1008 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1010 store_reg_to_var_int(iptr->dst, d);
1013 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1014 /* val.i = constant */
1016 var_to_reg_int(s1, src, REG_ITMP1);
1017 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1018 M_LSLL_IMM(s1, iptr->val.i, d);
1019 store_reg_to_var_int(iptr->dst, d);
1022 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1024 var_to_reg_int(s1, src->prev, REG_ITMP1);
1025 var_to_reg_int(s2, src, REG_ITMP2);
1026 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1028 store_reg_to_var_int(iptr->dst, d);
1031 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1032 /* val.i = constant */
1034 var_to_reg_int(s1, src, REG_ITMP1);
1035 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1036 M_LSRA_IMM(s1, iptr->val.i, d);
1037 store_reg_to_var_int(iptr->dst, d);
1040 case ICMD_LUSHR: /* ..., 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_ITMP2);
1046 store_reg_to_var_int(iptr->dst, d);
1049 case ICMD_LUSHRCONST: /* ..., 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_ITMP2);
1054 M_LSRL_IMM(s1, iptr->val.i, d);
1055 store_reg_to_var_int(iptr->dst, d);
1058 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1061 var_to_reg_int(s1, src->prev, REG_ITMP1);
1062 var_to_reg_int(s2, src, REG_ITMP2);
1063 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1065 store_reg_to_var_int(iptr->dst, d);
1068 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1069 /* val.i = constant */
1071 var_to_reg_int(s1, src, REG_ITMP1);
1072 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1073 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1074 M_AND_IMM(s1, iptr->val.i, d);
1076 ICONST(REG_ITMP2, iptr->val.i);
1077 M_AND(s1, REG_ITMP2, d);
1079 store_reg_to_var_int(iptr->dst, d);
1082 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1083 /* val.i = constant */
1085 var_to_reg_int(s1, src, REG_ITMP1);
1086 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1088 M_MOV(s1, REG_ITMP1);
1091 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1092 M_AND_IMM(s1, iptr->val.i, d);
1095 M_ISUB(REG_ZERO, s1, d);
1096 M_AND_IMM(d, iptr->val.i, d);
1098 ICONST(REG_ITMP2, iptr->val.i);
1099 M_AND(s1, REG_ITMP2, d);
1102 M_ISUB(REG_ZERO, s1, d);
1103 M_AND(d, REG_ITMP2, d);
1105 M_ISUB(REG_ZERO, d, d);
1106 store_reg_to_var_int(iptr->dst, d);
1109 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1110 /* val.l = constant */
1112 var_to_reg_int(s1, src, REG_ITMP1);
1113 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1114 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1115 M_AND_IMM(s1, iptr->val.l, d);
1117 LCONST(REG_ITMP2, iptr->val.l);
1118 M_AND(s1, REG_ITMP2, d);
1120 store_reg_to_var_int(iptr->dst, d);
1123 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1124 /* val.l = constant */
1126 var_to_reg_int(s1, src, REG_ITMP1);
1127 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1129 M_MOV(s1, REG_ITMP1);
1132 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1133 M_AND_IMM(s1, iptr->val.l, d);
1136 M_LSUB(REG_ZERO, s1, d);
1137 M_AND_IMM(d, iptr->val.l, d);
1139 LCONST(REG_ITMP2, iptr->val.l);
1140 M_AND(s1, REG_ITMP2, d);
1143 M_LSUB(REG_ZERO, s1, d);
1144 M_AND(d, REG_ITMP2, d);
1146 M_LSUB(REG_ZERO, d, d);
1147 store_reg_to_var_int(iptr->dst, d);
1150 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1153 var_to_reg_int(s1, src->prev, REG_ITMP1);
1154 var_to_reg_int(s2, src, REG_ITMP2);
1155 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1157 store_reg_to_var_int(iptr->dst, d);
1160 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1161 /* val.i = constant */
1163 var_to_reg_int(s1, src, REG_ITMP1);
1164 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1165 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1166 M_OR_IMM(s1, iptr->val.i, d);
1168 ICONST(REG_ITMP2, iptr->val.i);
1169 M_OR(s1, REG_ITMP2, d);
1171 store_reg_to_var_int(iptr->dst, d);
1174 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1175 /* val.l = constant */
1177 var_to_reg_int(s1, src, REG_ITMP1);
1178 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1179 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1180 M_OR_IMM(s1, iptr->val.l, d);
1182 LCONST(REG_ITMP2, iptr->val.l);
1183 M_OR(s1, REG_ITMP2, d);
1185 store_reg_to_var_int(iptr->dst, d);
1188 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1191 var_to_reg_int(s1, src->prev, REG_ITMP1);
1192 var_to_reg_int(s2, src, REG_ITMP2);
1193 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1195 store_reg_to_var_int(iptr->dst, d);
1198 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1199 /* val.i = constant */
1201 var_to_reg_int(s1, src, REG_ITMP1);
1202 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1203 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1204 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_LXORCONST: /* ..., value ==> ..., value ^ constant */
1213 /* val.l = constant */
1215 var_to_reg_int(s1, src, REG_ITMP1);
1216 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1217 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1218 M_XOR_IMM(s1, iptr->val.l, d);
1220 LCONST(REG_ITMP2, iptr->val.l);
1221 M_XOR(s1, REG_ITMP2, d);
1223 store_reg_to_var_int(iptr->dst, d);
1227 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1229 var_to_reg_int(s1, src->prev, REG_ITMP1);
1230 var_to_reg_int(s2, src, REG_ITMP2);
1231 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1232 M_CMPLT(s1, s2, REG_ITMP3);
1233 M_CMPLT(s2, s1, REG_ITMP1);
1234 M_LSUB(REG_ITMP1, REG_ITMP3, d);
1235 store_reg_to_var_int(iptr->dst, d);
1239 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1240 /* op1 = variable, val.i = constant */
1242 var = &(rd->locals[iptr->op1][TYPE_INT]);
1243 if (var->flags & INMEMORY) {
1245 M_LLD(s1, REG_SP, var->regoff * 8);
1248 M_IADD_IMM(s1, iptr->val.i, s1);
1249 if (var->flags & INMEMORY)
1250 M_LST(s1, REG_SP, var->regoff * 8);
1254 /* floating operations ************************************************/
1256 case ICMD_FNEG: /* ..., value ==> ..., - value */
1258 var_to_reg_flt(s1, src, REG_FTMP1);
1259 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1261 store_reg_to_var_flt(iptr->dst, d);
1264 case ICMD_DNEG: /* ..., value ==> ..., - value */
1266 var_to_reg_flt(s1, src, REG_FTMP1);
1267 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1269 store_reg_to_var_flt(iptr->dst, d);
1272 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1274 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1275 var_to_reg_flt(s2, src, REG_FTMP2);
1276 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1278 store_reg_to_var_flt(iptr->dst, d);
1281 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1283 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1284 var_to_reg_flt(s2, src, REG_FTMP2);
1285 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1287 store_reg_to_var_flt(iptr->dst, d);
1290 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1292 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1293 var_to_reg_flt(s2, src, REG_FTMP2);
1294 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1296 store_reg_to_var_flt(iptr->dst, d);
1299 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1301 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1302 var_to_reg_flt(s2, src, REG_FTMP2);
1303 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1305 store_reg_to_var_flt(iptr->dst, d);
1308 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1310 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1311 var_to_reg_flt(s2, src, REG_FTMP2);
1312 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1314 store_reg_to_var_flt(iptr->dst, d);
1317 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1319 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1320 var_to_reg_flt(s2, src, REG_FTMP2);
1321 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1323 store_reg_to_var_flt(iptr->dst, d);
1326 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1328 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1329 var_to_reg_flt(s2, src, REG_FTMP2);
1330 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1332 store_reg_to_var_flt(iptr->dst, d);
1335 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1337 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1338 var_to_reg_flt(s2, src, REG_FTMP2);
1339 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1341 store_reg_to_var_flt(iptr->dst, d);
1345 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1347 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1348 var_to_reg_flt(s2, src, REG_FTMP2);
1349 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1350 M_FDIV(s1,s2, REG_FTMP3);
1351 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1352 M_CVTLF(REG_FTMP3, REG_FTMP3);
1353 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1354 M_FSUB(s1, REG_FTMP3, d);
1355 store_reg_to_var_flt(iptr->dst, d);
1358 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1360 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1361 var_to_reg_flt(s2, src, REG_FTMP2);
1362 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1363 M_DDIV(s1,s2, REG_FTMP3);
1364 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1365 M_CVTLD(REG_FTMP3, REG_FTMP3);
1366 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1367 M_DSUB(s1, REG_FTMP3, d);
1368 store_reg_to_var_flt(iptr->dst, d);
1372 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1374 var_to_reg_int(s1, src, REG_ITMP1);
1375 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1378 store_reg_to_var_flt(iptr->dst, d);
1381 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1383 var_to_reg_int(s1, src, REG_ITMP1);
1384 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1387 store_reg_to_var_flt(iptr->dst, d);
1390 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1392 var_to_reg_flt(s1, src, REG_FTMP1);
1393 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1394 M_TRUNCFI(s1, REG_FTMP1);
1395 M_MOVDI(REG_FTMP1, d);
1397 store_reg_to_var_int(iptr->dst, d);
1400 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1402 var_to_reg_flt(s1, src, REG_FTMP1);
1403 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1404 M_TRUNCDI(s1, REG_FTMP1);
1405 M_MOVDI(REG_FTMP1, d);
1407 store_reg_to_var_int(iptr->dst, d);
1410 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1412 var_to_reg_flt(s1, src, REG_FTMP1);
1413 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1414 M_TRUNCFL(s1, REG_FTMP1);
1415 M_MOVDL(REG_FTMP1, d);
1417 store_reg_to_var_int(iptr->dst, d);
1420 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1422 var_to_reg_flt(s1, src, REG_FTMP1);
1423 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1424 M_TRUNCDL(s1, REG_FTMP1);
1425 M_MOVDL(REG_FTMP1, d);
1427 store_reg_to_var_int(iptr->dst, d);
1430 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1432 var_to_reg_flt(s1, src, REG_FTMP1);
1433 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1435 store_reg_to_var_flt(iptr->dst, d);
1438 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1440 var_to_reg_flt(s1, src, REG_FTMP1);
1441 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1443 store_reg_to_var_flt(iptr->dst, d);
1446 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1448 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1449 var_to_reg_flt(s2, src, REG_FTMP2);
1450 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1453 M_LADD_IMM(REG_ZERO, 1, d);
1457 M_LSUB_IMM(REG_ZERO, 1, d);
1458 M_CMOVT(REG_ZERO, d);
1459 store_reg_to_var_int(iptr->dst, d);
1462 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1464 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1465 var_to_reg_flt(s2, src, REG_FTMP2);
1466 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1469 M_LADD_IMM(REG_ZERO, 1, d);
1473 M_LSUB_IMM(REG_ZERO, 1, d);
1474 M_CMOVT(REG_ZERO, d);
1475 store_reg_to_var_int(iptr->dst, d);
1478 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1480 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1481 var_to_reg_flt(s2, src, REG_FTMP2);
1482 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1485 M_LSUB_IMM(REG_ZERO, 1, d);
1489 M_LADD_IMM(REG_ZERO, 1, d);
1490 M_CMOVT(REG_ZERO, d);
1491 store_reg_to_var_int(iptr->dst, d);
1494 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1496 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1497 var_to_reg_flt(s2, src, REG_FTMP2);
1498 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1501 M_LSUB_IMM(REG_ZERO, 1, d);
1505 M_LADD_IMM(REG_ZERO, 1, d);
1506 M_CMOVT(REG_ZERO, d);
1507 store_reg_to_var_int(iptr->dst, d);
1511 /* memory operations **************************************************/
1513 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1515 var_to_reg_int(s1, src, REG_ITMP1);
1516 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1517 gen_nullptr_check(s1);
1518 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1519 store_reg_to_var_int(iptr->dst, d);
1522 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1524 var_to_reg_int(s1, src->prev, REG_ITMP1);
1525 var_to_reg_int(s2, src, REG_ITMP2);
1526 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1527 if (iptr->op1 == 0) {
1528 gen_nullptr_check(s1);
1531 M_AADD(s2, s1, REG_ITMP1);
1532 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1533 store_reg_to_var_int(iptr->dst, d);
1536 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1538 var_to_reg_int(s1, src->prev, REG_ITMP1);
1539 var_to_reg_int(s2, src, REG_ITMP2);
1540 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1541 if (iptr->op1 == 0) {
1542 gen_nullptr_check(s1);
1545 M_AADD(s2, s1, REG_ITMP1);
1546 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1547 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1548 store_reg_to_var_int(iptr->dst, d);
1551 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1553 var_to_reg_int(s1, src->prev, REG_ITMP1);
1554 var_to_reg_int(s2, src, REG_ITMP2);
1555 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1556 if (iptr->op1 == 0) {
1557 gen_nullptr_check(s1);
1560 M_AADD(s2, s1, REG_ITMP1);
1561 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1562 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1563 store_reg_to_var_int(iptr->dst, d);
1566 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1568 var_to_reg_int(s1, src->prev, REG_ITMP1);
1569 var_to_reg_int(s2, src, REG_ITMP2);
1570 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1571 if (iptr->op1 == 0) {
1572 gen_nullptr_check(s1);
1575 M_ASLL_IMM(s2, 2, REG_ITMP2);
1576 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1577 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1578 store_reg_to_var_int(iptr->dst, d);
1581 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1583 var_to_reg_int(s1, src->prev, REG_ITMP1);
1584 var_to_reg_int(s2, src, REG_ITMP2);
1585 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1586 if (iptr->op1 == 0) {
1587 gen_nullptr_check(s1);
1590 M_ASLL_IMM(s2, 3, REG_ITMP2);
1591 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1592 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1593 store_reg_to_var_int(iptr->dst, d);
1596 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1598 var_to_reg_int(s1, src->prev, REG_ITMP1);
1599 var_to_reg_int(s2, src, REG_ITMP2);
1600 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1601 if (iptr->op1 == 0) {
1602 gen_nullptr_check(s1);
1605 M_ASLL_IMM(s2, 2, REG_ITMP2);
1606 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1607 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1608 store_reg_to_var_flt(iptr->dst, d);
1611 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1613 var_to_reg_int(s1, src->prev, REG_ITMP1);
1614 var_to_reg_int(s2, src, REG_ITMP2);
1615 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1616 if (iptr->op1 == 0) {
1617 gen_nullptr_check(s1);
1620 M_ASLL_IMM(s2, 3, REG_ITMP2);
1621 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1622 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1623 store_reg_to_var_flt(iptr->dst, d);
1626 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1628 var_to_reg_int(s1, src->prev, REG_ITMP1);
1629 var_to_reg_int(s2, src, REG_ITMP2);
1630 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1631 if (iptr->op1 == 0) {
1632 gen_nullptr_check(s1);
1635 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1636 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1637 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1638 store_reg_to_var_int(iptr->dst, d);
1642 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1644 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1645 var_to_reg_int(s2, src->prev, REG_ITMP2);
1646 if (iptr->op1 == 0) {
1647 gen_nullptr_check(s1);
1650 var_to_reg_int(s3, src, REG_ITMP3);
1651 M_AADD(s2, s1, REG_ITMP1);
1652 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1655 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1656 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1658 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1659 var_to_reg_int(s2, src->prev, REG_ITMP2);
1660 if (iptr->op1 == 0) {
1661 gen_nullptr_check(s1);
1664 var_to_reg_int(s3, src, REG_ITMP3);
1665 M_AADD(s2, s1, REG_ITMP1);
1666 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1667 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1670 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1672 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1673 var_to_reg_int(s2, src->prev, REG_ITMP2);
1674 if (iptr->op1 == 0) {
1675 gen_nullptr_check(s1);
1678 var_to_reg_int(s3, src, REG_ITMP3);
1679 M_ASLL_IMM(s2, 2, REG_ITMP2);
1680 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1681 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1684 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1686 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1687 var_to_reg_int(s2, src->prev, REG_ITMP2);
1688 if (iptr->op1 == 0) {
1689 gen_nullptr_check(s1);
1692 var_to_reg_int(s3, src, REG_ITMP3);
1693 M_ASLL_IMM(s2, 3, REG_ITMP2);
1694 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1695 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1698 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1700 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1701 var_to_reg_int(s2, src->prev, REG_ITMP2);
1702 if (iptr->op1 == 0) {
1703 gen_nullptr_check(s1);
1706 var_to_reg_flt(s3, src, REG_FTMP1);
1707 M_ASLL_IMM(s2, 2, REG_ITMP2);
1708 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1709 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1712 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1714 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1715 var_to_reg_int(s2, src->prev, REG_ITMP2);
1716 if (iptr->op1 == 0) {
1717 gen_nullptr_check(s1);
1720 var_to_reg_flt(s3, src, REG_FTMP1);
1721 M_ASLL_IMM(s2, 3, REG_ITMP2);
1722 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1723 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1727 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1729 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1730 var_to_reg_int(s2, src->prev, REG_ITMP2);
1731 if (iptr->op1 == 0) {
1732 gen_nullptr_check(s1);
1735 var_to_reg_int(s3, src, REG_ITMP3);
1737 M_MOV(s1, rd->argintregs[0]);
1738 M_MOV(s3, rd->argintregs[1]);
1739 disp = dseg_addaddress(cd, BUILTIN_canstore);
1740 M_ALD(REG_ITMP3, REG_PV, disp);
1741 M_JSR(REG_RA, REG_ITMP3);
1744 M_BEQZ(REG_RESULT, 0);
1745 codegen_addxstorerefs(cd, mcodeptr);
1748 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1749 var_to_reg_int(s2, src->prev, REG_ITMP2);
1750 var_to_reg_int(s3, src, REG_ITMP3);
1751 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1752 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1753 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1757 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1759 var_to_reg_int(s1, src->prev, REG_ITMP1);
1760 var_to_reg_int(s2, src, REG_ITMP2);
1761 if (iptr->op1 == 0) {
1762 gen_nullptr_check(s1);
1765 M_ASLL_IMM(s2, 2, REG_ITMP2);
1766 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1767 M_IST(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1770 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1772 var_to_reg_int(s1, src->prev, REG_ITMP1);
1773 var_to_reg_int(s2, src, REG_ITMP2);
1774 if (iptr->op1 == 0) {
1775 gen_nullptr_check(s1);
1778 M_ASLL_IMM(s2, 3, REG_ITMP2);
1779 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1780 M_LST(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1783 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1785 var_to_reg_int(s1, src->prev, REG_ITMP1);
1786 var_to_reg_int(s2, src, REG_ITMP2);
1787 if (iptr->op1 == 0) {
1788 gen_nullptr_check(s1);
1791 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1792 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1793 M_AST(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1796 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1798 var_to_reg_int(s1, src->prev, REG_ITMP1);
1799 var_to_reg_int(s2, src, REG_ITMP2);
1800 if (iptr->op1 == 0) {
1801 gen_nullptr_check(s1);
1804 M_AADD(s2, s1, REG_ITMP1);
1805 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1808 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1809 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1811 var_to_reg_int(s1, src->prev, REG_ITMP1);
1812 var_to_reg_int(s2, src, REG_ITMP2);
1813 if (iptr->op1 == 0) {
1814 gen_nullptr_check(s1);
1817 M_AADD(s2, s1, REG_ITMP1);
1818 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1819 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
1823 case ICMD_GETSTATIC: /* ... ==> ..., value */
1824 /* op1 = type, val.a = field address */
1827 disp = dseg_addaddress(cd, NULL);
1829 codegen_addpatchref(cd, mcodeptr,
1830 PATCHER_get_putstatic,
1831 (unresolved_field *) iptr->target, disp);
1833 if (opt_showdisassemble) {
1838 fieldinfo *fi = iptr->val.a;
1840 disp = dseg_addaddress(cd, &(fi->value));
1842 if (!fi->class->initialized) {
1843 codegen_addpatchref(cd, mcodeptr,
1844 PATCHER_clinit, fi->class, 0);
1846 if (opt_showdisassemble) {
1852 M_ALD(REG_ITMP1, REG_PV, disp);
1853 switch (iptr->op1) {
1855 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1856 M_ILD_INTERN(d, REG_ITMP1, 0);
1857 store_reg_to_var_int(iptr->dst, d);
1860 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1861 M_LLD_INTERN(d, REG_ITMP1, 0);
1862 store_reg_to_var_int(iptr->dst, d);
1865 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1866 M_ALD_INTERN(d, REG_ITMP1, 0);
1867 store_reg_to_var_int(iptr->dst, d);
1870 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1871 M_FLD_INTERN(d, REG_ITMP1, 0);
1872 store_reg_to_var_flt(iptr->dst, d);
1875 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1876 M_DLD_INTERN(d, REG_ITMP1, 0);
1877 store_reg_to_var_flt(iptr->dst, d);
1882 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1883 /* op1 = type, val.a = field address */
1886 disp = dseg_addaddress(cd, NULL);
1888 codegen_addpatchref(cd, mcodeptr,
1889 PATCHER_get_putstatic,
1890 (unresolved_field *) iptr->target, disp);
1892 if (opt_showdisassemble) {
1897 fieldinfo *fi = iptr->val.a;
1899 disp = dseg_addaddress(cd, &(fi->value));
1901 if (!fi->class->initialized) {
1902 codegen_addpatchref(cd, mcodeptr,
1903 PATCHER_clinit, fi->class, 0);
1905 if (opt_showdisassemble) {
1911 M_ALD(REG_ITMP1, REG_PV, disp);
1912 switch (iptr->op1) {
1914 var_to_reg_int(s2, src, REG_ITMP2);
1915 M_IST_INTERN(s2, REG_ITMP1, 0);
1918 var_to_reg_int(s2, src, REG_ITMP2);
1919 M_LST_INTERN(s2, REG_ITMP1, 0);
1922 var_to_reg_int(s2, src, REG_ITMP2);
1923 M_AST_INTERN(s2, REG_ITMP1, 0);
1926 var_to_reg_flt(s2, src, REG_FTMP2);
1927 M_FST_INTERN(s2, REG_ITMP1, 0);
1930 var_to_reg_flt(s2, src, REG_FTMP2);
1931 M_DST_INTERN(s2, REG_ITMP1, 0);
1936 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1937 /* val = value (in current instruction) */
1938 /* op1 = type, val.a = field address (in */
1939 /* following NOP) */
1941 if (!iptr[1].val.a) {
1942 disp = dseg_addaddress(cd, NULL);
1944 codegen_addpatchref(cd, mcodeptr,
1945 PATCHER_get_putstatic,
1946 (unresolved_field *) iptr[1].target, disp);
1948 if (opt_showdisassemble) {
1953 fieldinfo *fi = iptr[1].val.a;
1955 disp = dseg_addaddress(cd, &(fi->value));
1957 if (!fi->class->initialized) {
1958 codegen_addpatchref(cd, mcodeptr,
1959 PATCHER_clinit, fi->class, 0);
1961 if (opt_showdisassemble) {
1967 M_ALD(REG_ITMP1, REG_PV, disp);
1968 switch (iptr->op1) {
1970 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1973 M_LST_INTERN(REG_ZERO, REG_ITMP1, 0);
1976 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1979 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1982 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1988 case ICMD_GETFIELD: /* ... ==> ..., value */
1989 /* op1 = type, val.i = field offset */
1991 var_to_reg_int(s1, src, REG_ITMP1);
1992 gen_nullptr_check(s1);
1995 codegen_addpatchref(cd, mcodeptr,
1996 PATCHER_get_putfield,
1997 (unresolved_field *) iptr->target, 0);
1999 if (opt_showdisassemble) {
2006 a = ((fieldinfo *) (iptr->val.a))->offset;
2009 switch (iptr->op1) {
2011 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2013 store_reg_to_var_int(iptr->dst, d);
2016 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2018 store_reg_to_var_int(iptr->dst, d);
2021 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2023 store_reg_to_var_int(iptr->dst, d);
2026 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2028 store_reg_to_var_flt(iptr->dst, d);
2031 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2033 store_reg_to_var_flt(iptr->dst, d);
2038 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2039 /* op1 = type, val.a = field address */
2041 var_to_reg_int(s1, src->prev, REG_ITMP1);
2042 gen_nullptr_check(s1);
2044 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2045 var_to_reg_int(s2, src, REG_ITMP2);
2047 var_to_reg_flt(s2, src, REG_FTMP2);
2051 codegen_addpatchref(cd, mcodeptr,
2052 PATCHER_get_putfield,
2053 (unresolved_field *) iptr->target, 0);
2055 if (opt_showdisassemble) {
2062 a = ((fieldinfo *) (iptr->val.a))->offset;
2065 switch (iptr->op1) {
2084 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2085 /* val = value (in current instruction) */
2086 /* op1 = type, val.a = field address (in */
2087 /* following NOP) */
2089 var_to_reg_int(s1, src, REG_ITMP1);
2090 gen_nullptr_check(s1);
2092 if (!iptr[1].val.a) {
2093 codegen_addpatchref(cd, mcodeptr,
2094 PATCHER_get_putfield,
2095 (unresolved_field *) iptr[1].target, 0);
2097 if (opt_showdisassemble) {
2104 a = ((fieldinfo *) (iptr[1].val.a))->offset;
2107 switch (iptr[1].op1) {
2109 M_IST(REG_ZERO, s1, a);
2112 M_LST(REG_ZERO, s1, a);
2115 M_AST(REG_ZERO, s1, a);
2118 M_FST(REG_ZERO, s1, a);
2121 M_DST(REG_ZERO, s1, a);
2127 /* branch operations **************************************************/
2129 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2131 var_to_reg_int(s1, src, REG_ITMP1);
2132 M_INTMOVE(s1, REG_ITMP1_XPTR);
2135 codegen_addpatchref(cd, mcodeptr,
2136 PATCHER_athrow_areturn,
2137 (unresolved_class *) iptr->val.a, 0);
2139 if (opt_showdisassemble) {
2144 disp = dseg_addaddress(cd, asm_handle_exception);
2145 M_ALD(REG_ITMP2, REG_PV, disp);
2146 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2148 M_NOP; /* nop ensures that XPC is less than the end */
2149 /* of basic block */
2153 case ICMD_GOTO: /* ... ==> ... */
2154 /* op1 = target JavaVM pc */
2156 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2161 case ICMD_JSR: /* ... ==> ... */
2162 /* op1 = target JavaVM pc */
2164 dseg_addtarget(cd, (basicblock *) iptr->target);
2165 M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
2166 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2170 case ICMD_RET: /* ... ==> ... */
2171 /* op1 = local variable */
2172 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2173 if (var->flags & INMEMORY) {
2174 M_ALD(REG_ITMP1, REG_SP, var->regoff * 8);
2182 case ICMD_IFNULL: /* ..., value ==> ... */
2183 /* op1 = target JavaVM pc */
2185 var_to_reg_int(s1, src, REG_ITMP1);
2187 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2191 case ICMD_IFNONNULL: /* ..., value ==> ... */
2192 /* op1 = target JavaVM pc */
2194 var_to_reg_int(s1, src, REG_ITMP1);
2196 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2200 case ICMD_IFEQ: /* ..., value ==> ... */
2201 /* op1 = target JavaVM pc, val.i = constant */
2203 var_to_reg_int(s1, src, REG_ITMP1);
2204 if (iptr->val.i == 0) {
2207 ICONST(REG_ITMP2, iptr->val.i);
2208 M_BEQ(s1, REG_ITMP2, 0);
2210 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2214 case ICMD_IFLT: /* ..., value ==> ... */
2215 /* op1 = target JavaVM pc, val.i = constant */
2217 var_to_reg_int(s1, src, REG_ITMP1);
2218 if (iptr->val.i == 0) {
2221 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2222 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2224 ICONST(REG_ITMP2, iptr->val.i);
2225 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2227 M_BNEZ(REG_ITMP1, 0);
2229 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2233 case ICMD_IFLE: /* ..., value ==> ... */
2234 /* op1 = target JavaVM pc, val.i = constant */
2236 var_to_reg_int(s1, src, REG_ITMP1);
2237 if (iptr->val.i == 0) {
2241 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2242 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2243 M_BNEZ(REG_ITMP1, 0);
2246 ICONST(REG_ITMP2, iptr->val.i);
2247 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2248 M_BEQZ(REG_ITMP1, 0);
2251 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2255 case ICMD_IFNE: /* ..., value ==> ... */
2256 /* op1 = target JavaVM pc, val.i = constant */
2258 var_to_reg_int(s1, src, REG_ITMP1);
2259 if (iptr->val.i == 0) {
2263 ICONST(REG_ITMP2, iptr->val.i);
2264 M_BNE(s1, REG_ITMP2, 0);
2266 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2270 case ICMD_IFGT: /* ..., value ==> ... */
2271 /* op1 = target JavaVM pc, val.i = constant */
2273 var_to_reg_int(s1, src, REG_ITMP1);
2274 if (iptr->val.i == 0) {
2278 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2279 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2280 M_BEQZ(REG_ITMP1, 0);
2283 ICONST(REG_ITMP2, iptr->val.i);
2284 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2285 M_BNEZ(REG_ITMP1, 0);
2288 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2292 case ICMD_IFGE: /* ..., value ==> ... */
2293 /* op1 = target JavaVM pc, val.i = constant */
2295 var_to_reg_int(s1, src, REG_ITMP1);
2296 if (iptr->val.i == 0) {
2300 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2301 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2304 ICONST(REG_ITMP2, iptr->val.i);
2305 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2307 M_BEQZ(REG_ITMP1, 0);
2309 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2313 case ICMD_IF_LEQ: /* ..., value ==> ... */
2314 /* op1 = target JavaVM pc, val.l = constant */
2316 var_to_reg_int(s1, src, REG_ITMP1);
2317 if (iptr->val.l == 0) {
2321 LCONST(REG_ITMP2, iptr->val.l);
2322 M_BEQ(s1, REG_ITMP2, 0);
2324 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2328 case ICMD_IF_LLT: /* ..., value ==> ... */
2329 /* op1 = target JavaVM pc, val.l = constant */
2331 var_to_reg_int(s1, src, REG_ITMP1);
2332 if (iptr->val.l == 0) {
2336 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2337 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2340 LCONST(REG_ITMP2, iptr->val.l);
2341 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2343 M_BNEZ(REG_ITMP1, 0);
2345 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2349 case ICMD_IF_LLE: /* ..., value ==> ... */
2350 /* op1 = target JavaVM pc, val.l = constant */
2352 var_to_reg_int(s1, src, REG_ITMP1);
2353 if (iptr->val.l == 0) {
2357 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2358 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2359 M_BNEZ(REG_ITMP1, 0);
2362 LCONST(REG_ITMP2, iptr->val.l);
2363 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2364 M_BEQZ(REG_ITMP1, 0);
2367 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2371 case ICMD_IF_LNE: /* ..., value ==> ... */
2372 /* op1 = target JavaVM pc, val.l = constant */
2374 var_to_reg_int(s1, src, REG_ITMP1);
2375 if (iptr->val.l == 0) {
2379 LCONST(REG_ITMP2, iptr->val.l);
2380 M_BNE(s1, REG_ITMP2, 0);
2382 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2386 case ICMD_IF_LGT: /* ..., value ==> ... */
2387 /* op1 = target JavaVM pc, val.l = constant */
2389 var_to_reg_int(s1, src, REG_ITMP1);
2390 if (iptr->val.l == 0) {
2394 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2395 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2396 M_BEQZ(REG_ITMP1, 0);
2399 LCONST(REG_ITMP2, iptr->val.l);
2400 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2401 M_BNEZ(REG_ITMP1, 0);
2404 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2408 case ICMD_IF_LGE: /* ..., value ==> ... */
2409 /* op1 = target JavaVM pc, val.l = constant */
2411 var_to_reg_int(s1, src, REG_ITMP1);
2412 if (iptr->val.l == 0) {
2416 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2417 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2420 LCONST(REG_ITMP2, iptr->val.l);
2421 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2423 M_BEQZ(REG_ITMP1, 0);
2425 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2429 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2430 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2431 case ICMD_IF_ACMPEQ:
2433 var_to_reg_int(s1, src->prev, REG_ITMP1);
2434 var_to_reg_int(s2, src, REG_ITMP2);
2436 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2440 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2441 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2442 case ICMD_IF_ACMPNE:
2444 var_to_reg_int(s1, src->prev, REG_ITMP1);
2445 var_to_reg_int(s2, src, REG_ITMP2);
2447 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2451 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2452 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2454 var_to_reg_int(s1, src->prev, REG_ITMP1);
2455 var_to_reg_int(s2, src, REG_ITMP2);
2456 M_CMPLT(s1, s2, REG_ITMP1);
2457 M_BNEZ(REG_ITMP1, 0);
2458 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2462 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2463 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2465 var_to_reg_int(s1, src->prev, REG_ITMP1);
2466 var_to_reg_int(s2, src, REG_ITMP2);
2467 M_CMPGT(s1, s2, REG_ITMP1);
2468 M_BNEZ(REG_ITMP1, 0);
2469 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2473 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2474 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2476 var_to_reg_int(s1, src->prev, REG_ITMP1);
2477 var_to_reg_int(s2, src, REG_ITMP2);
2478 M_CMPGT(s1, s2, REG_ITMP1);
2479 M_BEQZ(REG_ITMP1, 0);
2480 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2484 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2485 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2487 var_to_reg_int(s1, src->prev, REG_ITMP1);
2488 var_to_reg_int(s2, src, REG_ITMP2);
2489 M_CMPLT(s1, s2, REG_ITMP1);
2490 M_BEQZ(REG_ITMP1, 0);
2491 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2495 #ifdef CONDITIONAL_LOADCONST
2496 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2498 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2501 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2502 /* val.i = constant */
2504 var_to_reg_int(s1, src, REG_ITMP1);
2505 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2507 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2508 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2509 M_CMPEQ(s1, REG_ZERO, d);
2510 store_reg_to_var_int(iptr->dst, d);
2513 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2514 M_CMPEQ(s1, REG_ZERO, d);
2516 store_reg_to_var_int(iptr->dst, d);
2520 M_MOV(s1, REG_ITMP1);
2523 ICONST(d, iptr[1].val.i);
2525 if ((s3 >= 0) && (s3 <= 255)) {
2526 M_CMOVEQ_IMM(s1, s3, d);
2528 ICONST(REG_ITMP2, s3);
2529 M_CMOVEQ(s1, REG_ITMP2, d);
2531 store_reg_to_var_int(iptr->dst, d);
2534 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2535 /* val.i = constant */
2537 var_to_reg_int(s1, src, REG_ITMP1);
2538 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2540 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2541 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2542 M_CMPEQ(s1, REG_ZERO, d);
2543 store_reg_to_var_int(iptr->dst, d);
2546 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2547 M_CMPEQ(s1, REG_ZERO, d);
2549 store_reg_to_var_int(iptr->dst, d);
2553 M_MOV(s1, REG_ITMP1);
2556 ICONST(d, iptr[1].val.i);
2558 if ((s3 >= 0) && (s3 <= 255)) {
2559 M_CMOVNE_IMM(s1, s3, d);
2561 ICONST(REG_ITMP3, s3);
2562 M_CMOVNE(s1, REG_ITMP3, d);
2564 store_reg_to_var_int(iptr->dst, d);
2567 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2568 /* val.i = constant */
2570 var_to_reg_int(s1, src, REG_ITMP1);
2571 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2573 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2574 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2575 M_CMPLT(s1, REG_ZERO, d);
2576 store_reg_to_var_int(iptr->dst, d);
2579 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2580 M_CMPLE(REG_ZERO, s1, d);
2581 store_reg_to_var_int(iptr->dst, d);
2585 M_MOV(s1, REG_ITMP1);
2588 ICONST(d, iptr[1].val.i);
2590 if ((s3 >= 0) && (s3 <= 255)) {
2591 M_CMOVLT_IMM(s1, s3, d);
2593 ICONST(REG_ITMP2, s3);
2594 M_CMOVLT(s1, REG_ITMP2, d);
2596 store_reg_to_var_int(iptr->dst, d);
2599 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2600 /* val.i = constant */
2602 var_to_reg_int(s1, src, REG_ITMP1);
2603 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2605 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2606 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2607 M_CMPLE(REG_ZERO, s1, d);
2608 store_reg_to_var_int(iptr->dst, d);
2611 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2612 M_CMPLT(s1, REG_ZERO, d);
2613 store_reg_to_var_int(iptr->dst, d);
2617 M_MOV(s1, REG_ITMP1);
2620 ICONST(d, iptr[1].val.i);
2622 if ((s3 >= 0) && (s3 <= 255)) {
2623 M_CMOVGE_IMM(s1, s3, d);
2625 ICONST(REG_ITMP2, s3);
2626 M_CMOVGE(s1, REG_ITMP2, d);
2628 store_reg_to_var_int(iptr->dst, d);
2631 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2632 /* val.i = constant */
2634 var_to_reg_int(s1, src, REG_ITMP1);
2635 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2637 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2638 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2639 M_CMPLT(REG_ZERO, s1, d);
2640 store_reg_to_var_int(iptr->dst, d);
2643 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2644 M_CMPLE(s1, REG_ZERO, d);
2645 store_reg_to_var_int(iptr->dst, d);
2649 M_MOV(s1, REG_ITMP1);
2652 ICONST(d, iptr[1].val.i);
2654 if ((s3 >= 0) && (s3 <= 255)) {
2655 M_CMOVGT_IMM(s1, s3, d);
2657 ICONST(REG_ITMP2, s3);
2658 M_CMOVGT(s1, REG_ITMP2, d);
2660 store_reg_to_var_int(iptr->dst, d);
2663 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2664 /* val.i = constant */
2666 var_to_reg_int(s1, src, REG_ITMP1);
2667 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2669 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2670 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2671 M_CMPLE(s1, REG_ZERO, d);
2672 store_reg_to_var_int(iptr->dst, d);
2675 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2676 M_CMPLT(REG_ZERO, s1, d);
2677 store_reg_to_var_int(iptr->dst, d);
2681 M_MOV(s1, REG_ITMP1);
2684 ICONST(d, iptr[1].val.i);
2686 if ((s3 >= 0) && (s3 <= 255)) {
2687 M_CMOVLE_IMM(s1, s3, d);
2689 ICONST(REG_ITMP2, s3);
2690 M_CMOVLE(s1, REG_ITMP2, d);
2692 store_reg_to_var_int(iptr->dst, d);
2697 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2700 var_to_reg_int(s1, src, REG_RESULT);
2701 M_INTMOVE(s1, REG_RESULT);
2702 goto nowperformreturn;
2704 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2706 var_to_reg_int(s1, src, REG_RESULT);
2707 M_INTMOVE(s1, REG_RESULT);
2710 codegen_addpatchref(cd, mcodeptr,
2711 PATCHER_athrow_areturn,
2712 (unresolved_class *) iptr->val.a, 0);
2714 if (opt_showdisassemble) {
2718 goto nowperformreturn;
2720 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2722 var_to_reg_flt(s1, src, REG_FRESULT);
2724 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2725 M_TFLTMOVE(t, s1, REG_FRESULT);
2727 goto nowperformreturn;
2729 case ICMD_RETURN: /* ... ==> ... */
2735 p = parentargs_base;
2737 /* call trace function */
2740 M_LDA(REG_SP, REG_SP, -3 * 8);
2741 M_LST(REG_RA, REG_SP, 0 * 8);
2742 M_LST(REG_RESULT, REG_SP, 1 * 8);
2743 M_DST(REG_FRESULT, REG_SP, 2 * 8);
2745 disp = dseg_addaddress(cd, m);
2746 M_ALD(rd->argintregs[0], REG_PV, disp);
2747 M_MOV(REG_RESULT, rd->argintregs[1]);
2748 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2749 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
2751 disp = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2752 M_ALD(REG_ITMP3, REG_PV, disp);
2753 M_JSR(REG_RA, REG_ITMP3);
2756 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
2757 M_LLD(REG_RESULT, REG_SP, 1 * 8);
2758 M_LLD(REG_RA, REG_SP, 0 * 8);
2759 M_LDA(REG_SP, REG_SP, 3 * 8);
2762 #if defined(USE_THREADS)
2763 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2764 disp = dseg_addaddress(cd, (void *) builtin_monitorexit);
2765 M_ALD(REG_ITMP3, REG_PV, disp);
2767 /* we need to save the proper return value */
2769 switch (iptr->opc) {
2773 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2774 M_JSR(REG_RA, REG_ITMP3);
2775 M_LST(REG_RESULT, REG_SP, rd->memuse * 8); /* delay slot */
2779 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2780 M_JSR(REG_RA, REG_ITMP3);
2781 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8); /* delay slot */
2784 M_JSR(REG_RA, REG_ITMP3);
2785 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8); /* delay*/
2789 /* and now restore the proper return value */
2791 switch (iptr->opc) {
2795 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
2799 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
2805 /* restore return address */
2807 if (!m->isleafmethod) {
2808 p--; M_ALD(REG_RA, REG_SP, p * 8);
2811 /* restore saved registers */
2813 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2814 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
2816 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2817 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2820 /* deallocate stack and return */
2822 if (parentargs_base) {
2825 disp = parentargs_base * 8;
2826 lo = (short) (disp);
2827 hi = (short) (((disp) - lo) >> 16);
2831 M_LADD_IMM(REG_SP, lo, REG_SP); /* delay slot */
2833 M_LUI(REG_ITMP3,hi);
2834 M_LADD_IMM(REG_ITMP3,lo,REG_ITMP3);
2836 M_LADD(REG_ITMP3,REG_SP,REG_SP); /* delay slot */
2849 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2854 tptr = (void **) iptr->target;
2856 s4ptr = iptr->val.a;
2857 l = s4ptr[1]; /* low */
2858 i = s4ptr[2]; /* high */
2860 var_to_reg_int(s1, src, REG_ITMP1);
2862 {M_INTMOVE(s1, REG_ITMP1);}
2863 else if (l <= 32768) {
2864 M_IADD_IMM(s1, -l, REG_ITMP1);
2867 ICONST(REG_ITMP2, l);
2868 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2874 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
2875 M_BEQZ(REG_ITMP2, 0);
2876 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2877 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
2879 /* build jump table top down and use address of lowest entry */
2881 /* s4ptr += 3 + i; */
2885 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2886 dseg_addtarget(cd, (basicblock *) tptr[0]);
2891 /* length of dataseg after last dseg_addtarget is used by load */
2893 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2894 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2901 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2903 s4 i, /*l, */val, *s4ptr;
2906 tptr = (void **) iptr->target;
2908 s4ptr = iptr->val.a;
2909 /*l = s4ptr[0];*/ /* default */
2910 i = s4ptr[1]; /* count */
2912 MCODECHECK((i<<2)+8);
2913 var_to_reg_int(s1, src, REG_ITMP1);
2919 ICONST(REG_ITMP2, val);
2920 M_BEQ(s1, REG_ITMP2, 0);
2921 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2926 tptr = (void **) iptr->target;
2927 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2934 case ICMD_BUILTIN: /* ..., arg1 ==> ... */
2935 /* op1 = arg count val.a = builtintable entry */
2941 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2942 /* op1 = arg count, val.a = method pointer */
2944 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2945 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2946 case ICMD_INVOKEINTERFACE:
2951 unresolved_method *um = iptr->target;
2952 md = um->methodref->parseddesc.md;
2954 md = lm->parseddesc;
2958 s3 = md->paramcount;
2960 MCODECHECK((s3 << 1) + 64);
2962 /* copy arguments to registers or stack location */
2964 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2965 if (src->varkind == ARGVAR)
2967 if (IS_INT_LNG_TYPE(src->type)) {
2968 if (!md->params[s3].inmemory) {
2969 s1 = rd->argintregs[md->params[s3].regoff];
2970 var_to_reg_int(d, src, s1);
2973 var_to_reg_int(d, src, REG_ITMP1);
2974 M_LST(d, REG_SP, md->params[s3].regoff * 8);
2978 if (!md->params[s3].inmemory) {
2979 s1 = rd->argfltregs[md->params[s3].regoff];
2980 var_to_reg_flt(d, src, s1);
2981 M_TFLTMOVE(src->type, d, s1);
2983 var_to_reg_flt(d, src, REG_FTMP1);
2984 M_DST(d, REG_SP, md->params[s3].regoff * 8);
2989 switch (iptr->opc) {
2991 disp = dseg_addaddress(cd, bte->fp);
2992 d = md->returntype.type;
2994 M_ALD(REG_ITMP3, REG_PV, disp); /* built-in-function pointer */
2995 M_JSR(REG_RA, REG_ITMP3);
2997 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2998 M_LDA(REG_PV, REG_RA, -disp);
3000 /* if op1 == true, we need to check for an exception */
3002 if (iptr->op1 == true) {
3003 M_BEQZ(REG_RESULT, 0);
3004 codegen_addxexceptionrefs(cd, mcodeptr);
3009 case ICMD_INVOKESPECIAL:
3010 M_BEQZ(rd->argintregs[0], 0);
3011 codegen_addxnullrefs(cd, mcodeptr);
3015 case ICMD_INVOKESTATIC:
3017 unresolved_method *um = iptr->target;
3019 disp = dseg_addaddress(cd, NULL);
3021 codegen_addpatchref(cd, mcodeptr,
3022 PATCHER_invokestatic_special, um, disp);
3024 if (opt_showdisassemble) {
3028 d = um->methodref->parseddesc.md->returntype.type;
3031 disp = dseg_addaddress(cd, lm->stubroutine);
3032 d = lm->parseddesc->returntype.type;
3035 M_ALD(REG_PV, REG_PV, disp); /* method pointer in pv */
3036 M_JSR(REG_RA, REG_PV);
3038 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3039 M_LDA(REG_PV, REG_RA, -disp);
3042 case ICMD_INVOKEVIRTUAL:
3043 gen_nullptr_check(rd->argintregs[0]);
3046 unresolved_method *um = iptr->target;
3048 codegen_addpatchref(cd, mcodeptr,
3049 PATCHER_invokevirtual, um, 0);
3051 if (opt_showdisassemble) {
3056 d = um->methodref->parseddesc.md->returntype.type;
3059 s1 = OFFSET(vftbl_t, table[0]) +
3060 sizeof(methodptr) * lm->vftblindex;
3061 d = lm->parseddesc->returntype.type;
3064 M_ALD(REG_METHODPTR, rd->argintregs[0],
3065 OFFSET(java_objectheader, vftbl));
3066 M_ALD(REG_PV, REG_METHODPTR, s1);
3067 M_JSR(REG_RA, REG_PV);
3069 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3070 M_LDA(REG_PV, REG_RA, -disp);
3073 case ICMD_INVOKEINTERFACE:
3074 gen_nullptr_check(rd->argintregs[0]);
3077 unresolved_method *um = iptr->target;
3079 codegen_addpatchref(cd, mcodeptr,
3080 PATCHER_invokeinterface, um, 0);
3082 if (opt_showdisassemble) {
3088 d = um->methodref->parseddesc.md->returntype.type;
3091 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3092 sizeof(methodptr*) * lm->class->index;
3094 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3096 d = lm->parseddesc->returntype.type;
3099 M_ALD(REG_METHODPTR, rd->argintregs[0],
3100 OFFSET(java_objectheader, vftbl));
3101 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3102 M_ALD(REG_PV, REG_METHODPTR, s2);
3103 M_JSR(REG_RA, REG_PV);
3105 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3106 M_LDA(REG_PV, REG_RA, -disp);
3110 /* d contains return type */
3112 if (d != TYPE_VOID) {
3113 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3114 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3115 M_INTMOVE(REG_RESULT, s1);
3116 store_reg_to_var_int(iptr->dst, s1);
3118 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3119 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3120 store_reg_to_var_flt(iptr->dst, s1);
3126 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3127 /* op1: 0 == array, 1 == class */
3128 /* val.a: (classinfo*) superclass */
3130 /* superclass is an interface:
3132 * OK if ((sub == NULL) ||
3133 * (sub->vftbl->interfacetablelength > super->index) &&
3134 * (sub->vftbl->interfacetable[-super->index] != NULL));
3136 * superclass is a class:
3138 * OK if ((sub == NULL) || (0
3139 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3140 * super->vftbl->diffvall));
3143 if (iptr->op1 == 1) {
3145 vftbl_t *supervftbl;
3148 super = (classinfo *) iptr->val.a;
3155 superindex = super->index;
3156 supervftbl = super->vftbl;
3159 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3160 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3163 var_to_reg_int(s1, src, REG_ITMP1);
3165 /* calculate interface checkcast code size */
3169 s2 += (opt_showdisassemble ? 2 : 0);
3171 /* calculate class checkcast code size */
3173 s3 = 10 /* 10 + (s1 == REG_ITMP1) */;
3175 s3 += (opt_showdisassemble ? 2 : 0);
3177 /* if class is not resolved, check which code to call */
3180 M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
3183 disp = dseg_adds4(cd, 0); /* super->flags */
3185 codegen_addpatchref(cd, mcodeptr,
3186 PATCHER_checkcast_instanceof_flags,
3187 (constant_classref *) iptr->target,
3190 if (opt_showdisassemble) {
3194 /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
3195 M_ILD(REG_ITMP2, REG_PV, disp);
3196 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3197 M_BEQZ(REG_ITMP2, 1 + s2 + 2);
3201 /* interface checkcast code */
3203 if (!super || super->flags & ACC_INTERFACE) {
3209 codegen_addpatchref(cd, mcodeptr,
3210 PATCHER_checkcast_instanceof_interface,
3211 (constant_classref *) iptr->target,
3214 if (opt_showdisassemble) {
3219 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3220 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3221 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3222 M_BLEZ(REG_ITMP3, 0);
3223 codegen_addxcastrefs(cd, mcodeptr);
3225 M_ALD(REG_ITMP3, REG_ITMP2,
3226 OFFSET(vftbl_t, interfacetable[0]) -
3227 superindex * sizeof(methodptr*));
3228 M_BEQZ(REG_ITMP3, 0);
3229 codegen_addxcastrefs(cd, mcodeptr);
3238 /* class checkcast code */
3240 if (!super || !(super->flags & ACC_INTERFACE)) {
3241 disp = dseg_addaddress(cd, (void *) supervftbl);
3248 codegen_addpatchref(cd, mcodeptr,
3249 PATCHER_checkcast_instanceof_class,
3250 (constant_classref *) iptr->target,
3253 if (opt_showdisassemble) {
3258 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3259 M_ALD(REG_ITMP3, REG_PV, disp);
3260 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3261 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3263 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3264 /* if (s1 != REG_ITMP1) { */
3265 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3266 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3267 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3268 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3270 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3272 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3273 M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3274 M_ALD(REG_ITMP3, REG_PV, disp);
3275 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3276 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3277 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3280 M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3281 M_BNEZ(REG_ITMP3, 0);
3282 codegen_addxcastrefs(cd, mcodeptr);
3285 d = reg_of_var(rd, iptr->dst, s1);
3288 var_to_reg_int(s1, src, rd->argintregs[0]);
3289 M_INTMOVE(s1, rd->argintregs[0]);
3291 disp = dseg_addaddress(cd, iptr->val.a);
3293 if (iptr->val.a == NULL) {
3294 codegen_addpatchref(cd, mcodeptr,
3295 PATCHER_builtin_arraycheckcast,
3296 (constant_classref *) iptr->target,
3299 if (opt_showdisassemble) {
3304 M_ALD(rd->argintregs[1], REG_PV, disp);
3305 disp = dseg_addaddress(cd, BUILTIN_arraycheckcast);
3306 M_ALD(REG_ITMP3, REG_PV, disp);
3307 M_JSR(REG_RA, REG_ITMP3);
3310 M_BEQZ(REG_RESULT, 0);
3311 codegen_addxcastrefs(cd, mcodeptr);
3314 var_to_reg_int(s1, src, REG_ITMP1);
3315 d = reg_of_var(rd, iptr->dst, s1);
3318 store_reg_to_var_int(iptr->dst, d);
3321 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3322 /* op1: 0 == array, 1 == class */
3323 /* val.a: (classinfo*) superclass */
3325 /* superclass is an interface:
3327 * return (sub != NULL) &&
3328 * (sub->vftbl->interfacetablelength > super->index) &&
3329 * (sub->vftbl->interfacetable[-super->index] != NULL);
3331 * superclass is a class:
3333 * return ((sub != NULL) && (0
3334 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3335 * super->vftbl->diffvall));
3340 vftbl_t *supervftbl;
3343 super = (classinfo *) iptr->val.a;
3350 superindex = super->index;
3351 supervftbl = super->vftbl;
3354 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3355 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3358 var_to_reg_int(s1, src, REG_ITMP1);
3359 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3361 M_MOV(s1, REG_ITMP1);
3365 /* calculate interface instanceof code size */
3369 s2 += (opt_showdisassemble ? 2 : 0);
3371 /* calculate class instanceof code size */
3375 s3 += (opt_showdisassemble ? 2 : 0);
3379 /* if class is not resolved, check which code to call */
3382 M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
3385 disp = dseg_adds4(cd, 0); /* super->flags */
3387 codegen_addpatchref(cd, mcodeptr,
3388 PATCHER_checkcast_instanceof_flags,
3389 (constant_classref *) iptr->target, disp);
3391 if (opt_showdisassemble) {
3395 /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
3396 M_ILD(REG_ITMP3, REG_PV, disp);
3397 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
3398 M_BEQZ(REG_ITMP3, 1 + s2 + 2);
3402 /* interface instanceof code */
3404 if (!super || (super->flags & ACC_INTERFACE)) {
3410 codegen_addpatchref(cd, mcodeptr,
3411 PATCHER_checkcast_instanceof_interface,
3412 (constant_classref *) iptr->target, 0);
3414 if (opt_showdisassemble) {
3419 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3420 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3421 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3422 M_BLEZ(REG_ITMP3, 3);
3424 M_ALD(REG_ITMP1, REG_ITMP1,
3425 OFFSET(vftbl_t, interfacetable[0]) -
3426 superindex * sizeof(methodptr*));
3427 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3435 /* class instanceof code */
3437 if (!super || !(super->flags & ACC_INTERFACE)) {
3438 disp = dseg_addaddress(cd, supervftbl);
3445 codegen_addpatchref(cd, mcodeptr,
3446 PATCHER_checkcast_instanceof_class,
3447 (constant_classref *) iptr->target,
3450 if (opt_showdisassemble) {
3455 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3456 M_ALD(REG_ITMP2, REG_PV, disp);
3457 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3458 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3460 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3461 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3462 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3463 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3464 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3466 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3467 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3470 store_reg_to_var_int(iptr->dst, d);
3474 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3475 /* op1 = dimension, val.a = array descriptor */
3477 /* check for negative sizes and copy sizes to stack if necessary */
3479 MCODECHECK((iptr->op1 << 1) + 64);
3481 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3482 /* copy SAVEDVAR sizes to stack */
3484 if (src->varkind != ARGVAR) {
3485 var_to_reg_int(s2, src, REG_ITMP1);
3486 M_LST(s2, REG_SP, s1 * 8);
3490 /* a0 = dimension count */
3492 ICONST(rd->argintregs[0], iptr->op1);
3494 /* is patcher function set? */
3497 disp = dseg_addaddress(cd, NULL);
3499 codegen_addpatchref(cd, mcodeptr,
3500 PATCHER_builtin_multianewarray,
3503 if (opt_showdisassemble) {
3508 disp = dseg_addaddress(cd, iptr->val.a);
3511 /* a1 = arraydescriptor */
3513 M_ALD(rd->argintregs[1], REG_PV, disp);
3515 /* a2 = pointer to dimensions = stack pointer */
3517 M_INTMOVE(REG_SP, rd->argintregs[2]);
3519 disp = dseg_addaddress(cd, BUILTIN_multianewarray);
3520 M_ALD(REG_ITMP3, REG_PV, disp);
3521 M_JSR(REG_RA, REG_ITMP3);
3524 /* check for exception before result assignment */
3526 M_BEQZ(REG_RESULT, 0);
3527 codegen_addxexceptionrefs(cd, mcodeptr);
3530 d = reg_of_var(rd, iptr->dst, REG_RESULT);
3531 M_INTMOVE(REG_RESULT, d);
3532 store_reg_to_var_int(iptr->dst, d);
3536 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3540 } /* for instruction */
3542 /* copy values to interface registers */
3544 src = bptr->outstack;
3545 len = bptr->outdepth;
3552 if ((src->varkind != STACKVAR)) {
3554 if (IS_FLT_DBL_TYPE(s2)) {
3555 var_to_reg_flt(s1, src, REG_FTMP1);
3556 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3557 M_TFLTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3560 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3564 var_to_reg_int(s1, src, REG_ITMP1);
3565 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3566 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3569 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3576 /* At the end of a basic block we may have to append some nops,
3577 because the patcher stub calling code might be longer than the
3578 actual instruction. So codepatching does not change the
3579 following block unintentionally. */
3581 if ((u1 *) mcodeptr < cd->lastmcodeptr) {
3582 while ((u1 *) mcodeptr < cd->lastmcodeptr) {
3587 } /* if (bptr -> flags >= BBREACHED) */
3588 } /* for basic block */
3590 codegen_createlinenumbertable(cd);
3596 /* generate ArithmeticException stubs */
3600 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3601 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3603 (u1 *) mcodeptr - cd->mcodebase);
3607 if (xcodeptr != NULL) {
3608 M_BR(xcodeptr - mcodeptr);
3609 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3612 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3614 xcodeptr = mcodeptr;
3616 M_MOV(REG_PV, rd->argintregs[0]);
3617 M_MOV(REG_SP, rd->argintregs[1]);
3619 if (m->isleafmethod)
3620 M_MOV(REG_RA, rd->argintregs[2]);
3622 M_ALD(rd->argintregs[2],
3623 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3625 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3627 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3628 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3630 if (m->isleafmethod)
3631 M_AST(REG_RA, REG_SP, 1 * 8);
3633 a = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
3634 M_ALD(REG_ITMP3, REG_PV, a);
3635 M_JSR(REG_RA, REG_ITMP3);
3637 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3639 if (m->isleafmethod)
3640 M_ALD(REG_RA, REG_SP, 1 * 8);
3642 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3643 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3645 a = dseg_addaddress(cd, asm_handle_exception);
3646 M_ALD(REG_ITMP3, REG_PV, a);
3652 /* generate ArrayIndexOutOfBoundsException stubs */
3656 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3657 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3659 (u1 *) mcodeptr - cd->mcodebase);
3663 /* move index register into REG_ITMP1 */
3665 M_MOV(bref->reg, REG_ITMP1);
3666 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3668 if (xcodeptr != NULL) {
3669 M_BR(xcodeptr - mcodeptr);
3673 xcodeptr = mcodeptr;
3675 M_MOV(REG_PV, rd->argintregs[0]);
3676 M_MOV(REG_SP, rd->argintregs[1]);
3678 if (m->isleafmethod)
3679 M_MOV(REG_RA, rd->argintregs[2]);
3681 M_ALD(rd->argintregs[2],
3682 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3684 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3685 M_MOV(REG_ITMP1, rd->argintregs[4]);
3687 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3688 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3690 if (m->isleafmethod)
3691 M_AST(REG_RA, REG_SP, 1 * 8);
3693 a = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
3694 M_ALD(REG_ITMP3, REG_PV, a);
3695 M_JSR(REG_RA, REG_ITMP3);
3697 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3699 if (m->isleafmethod)
3700 M_ALD(REG_RA, REG_SP, 1 * 8);
3702 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3703 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3705 a = dseg_addaddress(cd, asm_handle_exception);
3706 M_ALD(REG_ITMP3, REG_PV, a);
3712 /* generate ArrayStoreException stubs */
3716 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
3717 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3719 (u1 *) mcodeptr - cd->mcodebase);
3723 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3725 if (xcodeptr != NULL) {
3726 M_BR(xcodeptr - mcodeptr);
3730 xcodeptr = mcodeptr;
3732 M_MOV(REG_PV, rd->argintregs[0]);
3733 M_MOV(REG_SP, rd->argintregs[1]);
3734 M_ALD(rd->argintregs[2],
3735 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3736 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3738 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3739 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3741 a = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
3742 M_ALD(REG_ITMP3, REG_PV, a);
3743 M_JSR(REG_RA, REG_ITMP3);
3745 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3747 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3748 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3750 a = dseg_addaddress(cd, asm_handle_exception);
3751 M_ALD(REG_ITMP3, REG_PV, a);
3757 /* generate ClassCastException stubs */
3761 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3762 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3764 (u1 *) mcodeptr - cd->mcodebase);
3768 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3770 if (xcodeptr != NULL) {
3771 M_BR(xcodeptr - mcodeptr);
3775 xcodeptr = mcodeptr;
3777 M_MOV(REG_PV, rd->argintregs[0]);
3778 M_MOV(REG_SP, rd->argintregs[1]);
3780 if (m->isleafmethod)
3781 M_MOV(REG_RA, rd->argintregs[2]);
3783 M_ALD(rd->argintregs[2],
3784 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3786 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3788 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3789 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3791 if (m->isleafmethod)
3792 M_AST(REG_RA, REG_SP, 1 * 8);
3794 a = dseg_addaddress(cd, stacktrace_inline_classcastexception);
3795 M_ALD(REG_ITMP3, REG_PV, a);
3796 M_JSR(REG_RA, REG_ITMP3);
3798 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3800 if (m->isleafmethod)
3801 M_ALD(REG_RA, REG_SP, 1 * 8);
3803 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3804 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3806 a = dseg_addaddress(cd, asm_handle_exception);
3807 M_ALD(REG_ITMP3, REG_PV, a);
3813 /* generate NullPointerException stubs */
3817 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3818 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3820 (u1 *) mcodeptr - cd->mcodebase);
3824 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3826 if (xcodeptr != NULL) {
3827 M_BR(xcodeptr - mcodeptr);
3831 xcodeptr = mcodeptr;
3833 M_MOV(REG_PV, rd->argintregs[0]);
3834 M_MOV(REG_SP, rd->argintregs[1]);
3836 if (m->isleafmethod)
3837 M_MOV(REG_RA, rd->argintregs[2]);
3839 M_ALD(rd->argintregs[2],
3840 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3842 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3844 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3845 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3847 if (m->isleafmethod)
3848 M_AST(REG_RA, REG_SP, 1 * 8);
3850 a = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
3851 M_ALD(REG_ITMP3, REG_PV, a);
3852 M_JSR(REG_RA, REG_ITMP3);
3854 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3856 if (m->isleafmethod)
3857 M_ALD(REG_RA, REG_SP, 1 * 8);
3859 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3860 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3862 a = dseg_addaddress(cd, asm_handle_exception);
3863 M_ALD(REG_ITMP3, REG_PV, a);
3869 /* generate exception check stubs */
3873 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3874 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3876 (u1 *) mcodeptr - cd->mcodebase);
3880 if (xcodeptr != NULL) {
3881 M_BR(xcodeptr - mcodeptr);
3882 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3885 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3887 xcodeptr = mcodeptr;
3889 M_MOV(REG_PV, rd->argintregs[0]);
3890 M_MOV(REG_SP, rd->argintregs[1]);
3891 M_ALD(rd->argintregs[2],
3892 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3893 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3895 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3896 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3898 a = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
3899 M_ALD(REG_ITMP3, REG_PV, a);
3900 M_JSR(REG_RA, REG_ITMP3);
3902 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3904 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3905 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3907 a = dseg_addaddress(cd, asm_handle_exception);
3908 M_ALD(REG_ITMP3, REG_PV, a);
3914 /* generate patcher stub call code */
3921 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3922 /* check code segment size */
3926 /* Get machine code which is patched back in later. The call is */
3927 /* 2 instruction words long. */
3929 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3931 /* We need to split this, because an unaligned 8 byte read causes */
3934 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3936 /* patch in the call to call the following code (done at compile */
3939 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3940 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3942 disp = (s4) (tmpmcodeptr - (xcodeptr + 1));
3944 if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) {
3946 new_internalerror("Jump offset is out of range: %d > +/-%d",
3954 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3956 /* create stack frame */
3958 M_ASUB_IMM(REG_SP, 6 * 8, REG_SP);
3960 /* calculate return address and move it onto the stack */
3962 M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
3963 M_AST(REG_ITMP3, REG_SP, 5 * 8);
3965 /* move pointer to java_objectheader onto stack */
3967 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3968 /* create a virtual java_objectheader */
3970 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3971 disp = dseg_addaddress(cd, NULL); /* vftbl */
3973 M_LDA(REG_ITMP3, REG_PV, disp);
3974 M_AST(REG_ITMP3, REG_SP, 4 * 8);
3979 /* move machine code onto stack */
3981 disp = dseg_adds8(cd, mcode);
3982 M_LLD(REG_ITMP3, REG_PV, disp);
3983 M_LST(REG_ITMP3, REG_SP, 3 * 8);
3985 /* move class/method/field reference onto stack */
3987 disp = dseg_addaddress(cd, pref->ref);
3988 M_ALD(REG_ITMP3, REG_PV, disp);
3989 M_AST(REG_ITMP3, REG_SP, 2 * 8);
3991 /* move data segment displacement onto stack */
3993 disp = dseg_adds4(cd, pref->disp);
3994 M_ILD(REG_ITMP3, REG_PV, disp);
3995 M_IST(REG_ITMP3, REG_SP, 1 * 8);
3997 /* move patcher function pointer onto stack */
3999 disp = dseg_addaddress(cd, pref->patcher);
4000 M_ALD(REG_ITMP3, REG_PV, disp);
4001 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4003 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4004 M_ALD(REG_ITMP3, REG_PV, disp);
4011 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4013 docacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4015 /* everything's ok */
4021 /* createcompilerstub **********************************************************
4023 Creates a stub routine which calls the compiler.
4025 *******************************************************************************/
4027 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
4028 #define COMPILERSTUB_CODESIZE 4 * 4
4030 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4033 functionptr createcompilerstub(methodinfo *m)
4035 ptrint *s; /* memory to hold the stub */
4036 s4 *mcodeptr; /* code generation pointer */
4038 s = (ptrint *) CNEW(u1, COMPILERSTUB_SIZE);
4041 s[1] = (ptrint) asm_call_jit_compiler;
4043 mcodeptr = (s4 *) (s + 2);
4045 M_ALD(REG_ITMP1, REG_PV, -2 * SIZEOF_VOID_P); /* method pointer */
4046 M_ALD(REG_PV, REG_PV, -1 * SIZEOF_VOID_P); /* pointer to compiler */
4050 (void) docacheflush((void *) s, (char *) mcodeptr - (char *) s);
4052 #if defined(STATISTICS)
4054 count_cstub_len += COMPILERSTUB_SIZE;
4057 return (functionptr) (((u1 *) s) + COMPILERSTUB_DATASIZE);
4061 /* createnativestub ************************************************************
4063 Creates a stub routine which calls a native method.
4065 *******************************************************************************/
4067 functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
4068 registerdata *rd, methoddesc *nmd)
4070 s4 *mcodeptr; /* code generation pointer */
4071 s4 stackframesize; /* size of stackframe if needed */
4074 s4 i, j; /* count variables */
4077 s4 funcdisp; /* displacement of the function */
4080 /* initialize variables */
4083 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4086 /* calculate stack frame size */
4089 1 + /* return address */
4090 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4091 sizeof(localref_table) / SIZEOF_VOID_P +
4092 md->paramcount + /* for saving arguments over calls */
4093 1 + /* for saving return address */
4097 /* create method header */
4099 #if SIZEOF_VOID_P == 4
4100 (void) dseg_addaddress(cd, m); /* MethodPointer */
4102 (void) dseg_addaddress(cd, m); /* MethodPointer */
4103 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4104 (void) dseg_adds4(cd, 0); /* IsSync */
4105 (void) dseg_adds4(cd, 0); /* IsLeaf */
4106 (void) dseg_adds4(cd, 0); /* IntSave */
4107 (void) dseg_adds4(cd, 0); /* FltSave */
4108 (void) dseg_addlinenumbertablesize(cd);
4109 (void) dseg_adds4(cd, 0); /* ExTableSize */
4112 /* initialize mcode variables */
4114 mcodeptr = (s4 *) cd->mcodebase;
4115 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
4118 /* generate stub code */
4120 M_LDA(REG_SP, REG_SP, -stackframesize * 8); /* build up stackframe */
4121 M_AST(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* store ra */
4124 /* call trace function */
4127 M_LDA(REG_SP, REG_SP, -(1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4129 /* save integer argument registers */
4131 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4132 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4133 M_LST(rd->argintregs[i], REG_SP, (1 + i) * 8);
4135 /* save and copy float arguments into integer registers */
4137 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4138 t = md->paramtypes[i].type;
4140 if (IS_FLT_DBL_TYPE(t)) {
4141 if (IS_2_WORD_TYPE(t)) {
4142 M_DST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4143 M_LLD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4145 M_FST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4146 M_ILD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4151 disp = dseg_addaddress(cd, m);
4152 M_ALD(REG_ITMP1, REG_PV, disp);
4153 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4154 disp = dseg_addaddress(cd, builtin_trace_args);
4155 M_ALD(REG_ITMP3, REG_PV, disp);
4156 M_JSR(REG_RA, REG_ITMP3);
4159 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4160 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4161 M_LLD(rd->argintregs[i], REG_SP, (1 + i) * 8);
4163 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4164 t = md->paramtypes[i].type;
4166 if (IS_FLT_DBL_TYPE(t)) {
4167 if (IS_2_WORD_TYPE(t)) {
4168 M_DLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4170 M_FLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4175 M_LDA(REG_SP, REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4179 /* get function address (this must happen before the stackframeinfo) */
4181 funcdisp = dseg_addaddress(cd, f);
4183 #if !defined(ENABLE_STATICVM)
4185 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m, funcdisp);
4187 if (opt_showdisassemble) {
4193 /* save integer and float argument registers */
4195 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4196 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4197 M_LST(rd->argintregs[i], REG_SP, j * 8);
4202 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4203 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4204 M_DST(rd->argfltregs[i], REG_SP, j * 8);
4209 /* prepare data structures for native function call */
4211 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4212 M_MOV(REG_PV, rd->argintregs[1]);
4213 M_AADD_IMM(REG_SP, stackframesize * 8, rd->argintregs[2]);
4214 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8 - SIZEOF_VOID_P);
4215 disp = dseg_addaddress(cd, codegen_start_native_call);
4216 M_ALD(REG_ITMP3, REG_PV, disp);
4217 M_JSR(REG_RA, REG_ITMP3);
4218 M_NOP; /* XXX fill me! */
4220 /* restore integer and float argument registers */
4222 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4223 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4224 M_LLD(rd->argintregs[i], REG_SP, j * 8);
4229 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4230 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4231 M_DLD(rd->argfltregs[i], REG_SP, j * 8);
4236 /* copy or spill arguments to new locations */
4238 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4239 t = md->paramtypes[i].type;
4241 if (IS_INT_LNG_TYPE(t)) {
4242 if (!md->params[i].inmemory) {
4243 s1 = rd->argintregs[md->params[i].regoff];
4245 if (!nmd->params[j].inmemory) {
4246 s2 = rd->argintregs[nmd->params[j].regoff];
4249 s2 = nmd->params[j].regoff;
4250 M_AST(s1, REG_SP, s2 * 8);
4254 s1 = md->params[i].regoff + stackframesize;
4255 s2 = nmd->params[j].regoff;
4256 M_ALD(REG_ITMP1, REG_SP, s1 * 8);
4257 M_AST(REG_ITMP1, REG_SP, s2 * 8);
4261 if (!md->params[i].inmemory) {
4262 s1 = rd->argfltregs[md->params[i].regoff];
4264 if (!nmd->params[j].inmemory) {
4265 s2 = rd->argfltregs[nmd->params[j].regoff];
4266 M_TFLTMOVE(t, s1, s2);
4268 s2 = nmd->params[j].regoff;
4269 if (IS_2_WORD_TYPE(t))
4270 M_DST(s1, REG_SP, s2 * 8);
4272 M_FST(s1, REG_SP, s2 * 8);
4276 s1 = md->params[i].regoff + stackframesize;
4277 s2 = nmd->params[j].regoff;
4278 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4279 if (IS_2_WORD_TYPE(t))
4280 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4282 M_FST(REG_FTMP1, REG_SP, s2 * 8);
4287 /* put class into second argument register */
4289 if (m->flags & ACC_STATIC) {
4290 disp = dseg_addaddress(cd, m->class);
4291 M_ALD(rd->argintregs[1], REG_PV, disp);
4294 /* put env into first argument register */
4296 disp = dseg_addaddress(cd, &env);
4297 M_ALD(rd->argintregs[0], REG_PV, disp);
4299 /* do the native function call */
4301 M_ALD(REG_ITMP3, REG_PV, funcdisp); /* load adress of native method */
4302 M_JSR(REG_RA, REG_ITMP3); /* call native method */
4303 M_NOP; /* delay slot */
4305 /* save return value */
4307 if (IS_INT_LNG_TYPE(md->returntype.type))
4308 M_LST(REG_RESULT, REG_SP, 0 * 8);
4310 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4312 /* remove native stackframe info */
4314 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4315 disp = dseg_addaddress(cd, codegen_finish_native_call);
4316 M_ALD(REG_ITMP3, REG_PV, disp);
4317 M_JSR(REG_RA, REG_ITMP3);
4318 M_NOP; /* XXX fill me! */
4320 /* call finished trace function */
4323 if (IS_INT_LNG_TYPE(md->returntype.type))
4324 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4326 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4328 disp = dseg_addaddress(cd, m);
4329 M_ALD(rd->argintregs[0], REG_PV, disp);
4331 M_MOV(REG_RESULT, rd->argintregs[1]);
4332 M_DMFC1(REG_ITMP1, REG_FRESULT);
4333 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4334 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4336 disp = dseg_addaddress(cd, builtin_displaymethodstop);
4337 M_ALD(REG_ITMP3, REG_PV, disp);
4338 M_JSR(REG_RA, REG_ITMP3);
4342 /* check for exception */
4344 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4345 disp = dseg_addaddress(cd, builtin_get_exceptionptrptr);
4346 M_ALD(REG_ITMP3, REG_PV, disp);
4347 M_JSR(REG_RA, REG_ITMP3);
4349 M_MOV(REG_RESULT, REG_ITMP3);
4351 disp = dseg_addaddress(cd, &_exceptionptr);
4352 M_ALD(REG_ITMP3, REG_PV, disp); /* get address of exceptionptr */
4354 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4356 M_ALD(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* load ra */
4358 /* restore return value */
4360 if (IS_INT_LNG_TYPE(md->returntype.type))
4361 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4363 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4365 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
4366 M_LDA(REG_SP, REG_SP, stackframesize * 8);/* remove stackframe, DELAY SLOT*/
4368 M_RET(REG_RA); /* return to caller */
4369 M_NOP; /* DELAY SLOT */
4371 /* handle exception */
4373 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4375 disp = dseg_addaddress(cd, asm_handle_nat_exception);
4376 M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */
4377 M_JMP(REG_ITMP3); /* jump to asm exception handler */
4378 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4381 /* generate static stub call code */
4389 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4390 /* Get machine code which is patched back in later. The call is */
4391 /* 2 instruction words long. */
4393 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4395 /* We need to split this, because an unaligned 8 byte read causes */
4398 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
4400 /* patch in the call to call the following code (done at compile */
4403 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4404 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4406 M_BRS(tmpmcodeptr - (xcodeptr + 1));
4407 M_NOP; /* branch delay slot */
4409 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4411 /* create stack frame */
4413 M_LSUB_IMM(REG_SP, 6 * 8, REG_SP);
4415 /* move return address onto stack */
4417 M_AST(REG_RA, REG_SP, 5 * 8);
4419 /* move pointer to java_objectheader onto stack */
4421 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4422 /* order reversed because of data segment layout */
4424 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4425 disp = dseg_addaddress(cd, NULL); /* vftbl */
4427 M_LDA(REG_ITMP3, REG_PV, disp);
4428 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4430 M_AST(REG_ZERO, REG_SP, 4 * 8);
4433 /* move machine code onto stack */
4435 disp = dseg_adds8(cd, mcode);
4436 M_LLD(REG_ITMP3, REG_PV, disp);
4437 M_LST(REG_ITMP3, REG_SP, 3 * 8);
4439 /* move class/method/field reference onto stack */
4441 disp = dseg_addaddress(cd, pref->ref);
4442 M_ALD(REG_ITMP3, REG_PV, disp);
4443 M_AST(REG_ITMP3, REG_SP, 2 * 8);
4445 /* move data segment displacement onto stack */
4447 disp = dseg_adds4(cd, pref->disp);
4448 M_ILD(REG_ITMP3, REG_PV, disp);
4449 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4451 /* move patcher function pointer onto stack */
4453 disp = dseg_addaddress(cd, pref->patcher);
4454 M_ALD(REG_ITMP3, REG_PV, disp);
4455 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4457 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4458 M_ALD(REG_ITMP3, REG_PV, disp);
4464 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4466 docacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4468 return m->entrypoint;
4473 * These are local overrides for various environment variables in Emacs.
4474 * Please do not remove this and leave it at the end of the file, where
4475 * Emacs will automagically detect them.
4476 * ---------------------------------------------------------------------
4479 * indent-tabs-mode: t