1 /* src/vm/jit/mips/codegen.c - machine code generator for MIPS
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, 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., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Andreas Krall
30 Changes: Christian Thalinger
34 Contains the codegenerator for an MIPS (R4000 or higher) processor.
35 This module generates MIPS machine code for a sequence of
36 intermediate code commands (ICMDs).
38 $Id: codegen.c 4357 2006-01-22 23:33:38Z twisti $
53 #include "vm/jit/mips/arch.h"
54 #include "vm/jit/mips/codegen.h"
56 #include "cacao/cacao.h"
57 #include "native/native.h"
58 #include "vm/builtin.h"
60 #include "vm/exceptions.h"
61 #include "vm/options.h"
62 #include "vm/stringlocal.h"
63 #include "vm/jit/asmpart.h"
64 #include "vm/jit/codegen-common.h"
65 #include "vm/jit/dseg.h"
66 #include "vm/jit/jit.h"
67 #include "vm/jit/patcher.h"
68 #include "vm/jit/reg.h"
70 #if defined(ENABLE_LSRA)
71 # include "vm/jit/allocator/lsra.h"
75 /* codegen *********************************************************************
77 Generates machine code.
79 *******************************************************************************/
81 bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
83 s4 len, s1, s2, s3, d, disp;
93 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
94 builtintable_entry *bte;
101 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
103 /* space to save used callee saved registers */
105 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
106 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
108 parentargs_base = rd->memuse + savedregs_num;
110 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
111 if (checksync && (m->flags & ACC_SYNCHRONIZED))
115 /* adjust frame size for 16 byte alignment */
117 if (parentargs_base & 1)
120 /* create method header */
122 #if SIZEOF_VOID_P == 4
123 (void) dseg_addaddress(cd, m); /* Filler */
125 (void) dseg_addaddress(cd, m); /* MethodPointer */
126 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
128 #if defined(USE_THREADS)
129 /* IsSync contains the offset relative to the stack pointer for the
130 argument of monitor_exit used in the exception handler. Since the
131 offset could be zero and give a wrong meaning of the flag it is
135 if (checksync && (m->flags & ACC_SYNCHRONIZED))
136 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
139 (void) dseg_adds4(cd, 0); /* IsSync */
141 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
142 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
143 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
144 dseg_addlinenumbertablesize(cd);
145 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
147 /* create exception table */
149 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
150 dseg_addtarget(cd, ex->start);
151 dseg_addtarget(cd, ex->end);
152 dseg_addtarget(cd, ex->handler);
153 (void) dseg_addaddress(cd, ex->catchtype.cls);
156 /* initialize mcode variables */
158 mcodeptr = (s4 *) cd->mcodeptr;
160 MCODECHECK(128 + m->paramcount);
162 /* initialize the last patcher pointer */
164 cd->lastmcodeptr = (u1 *) mcodeptr;
166 /* create stack frame (if necessary) */
169 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
171 /* save return address and used callee saved registers */
174 if (!m->isleafmethod) {
175 p--; M_AST(REG_RA, REG_SP, p * 8);
177 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
178 p--; M_AST(rd->savintregs[i], REG_SP, p * 8);
180 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
181 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
184 /* take arguments out of register or stack frame */
188 for (p = 0, l = 0; p < md->paramcount; p++) {
189 t = md->paramtypes[p].type;
190 var = &(rd->locals[l][t]);
192 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
196 s1 = md->params[p].regoff;
197 if (IS_INT_LNG_TYPE(t)) { /* integer args */
198 if (!md->params[p].inmemory) { /* register arguments */
199 s2 = rd->argintregs[s1];
200 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
201 M_INTMOVE(s2, var->regoff);
202 } else { /* reg arg -> spilled */
203 M_LST(s2, REG_SP, var->regoff * 8);
206 } else { /* stack arguments */
207 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
208 M_LLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
209 } else { /* stack arg -> spilled */
210 var->regoff = parentargs_base + s1;
214 } else { /* floating args */
215 if (!md->params[p].inmemory) { /* register arguments */
216 s2 = rd->argfltregs[s1];
217 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
218 M_TFLTMOVE(var->type, s2, var->regoff);
219 } else { /* reg arg -> spilled */
220 M_DST(s2, REG_SP, var->regoff * 8);
223 } else { /* stack arguments */
224 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
225 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
226 } else { /* stack-arg -> spilled */
227 var->regoff = parentargs_base + s1;
233 /* call monitorenter function */
235 #if defined(USE_THREADS)
236 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
237 /* stack offset for monitor argument */
242 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
244 for (p = 0; p < INT_ARG_CNT; p++)
245 M_LST(rd->argintregs[p], REG_SP, p * 8);
247 for (p = 0; p < FLT_ARG_CNT; p++)
248 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
250 s1 += INT_ARG_CNT + FLT_ARG_CNT;
253 /* decide which monitor enter function to call */
255 if (m->flags & ACC_STATIC) {
256 p = dseg_addaddress(cd, m->class);
257 M_ALD(rd->argintregs[0], REG_PV, p);
258 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
259 M_ALD(REG_ITMP3, REG_PV, p);
260 M_JSR(REG_RA, REG_ITMP3);
261 M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* branch delay */
264 M_BEQZ(rd->argintregs[0], 0);
265 codegen_addxnullrefs(cd, mcodeptr);
266 p = dseg_addaddress(cd, BUILTIN_monitorenter);
267 M_ALD(REG_ITMP3, REG_PV, p);
268 M_JSR(REG_RA, REG_ITMP3);
269 M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* branch delay */
273 for (p = 0; p < INT_ARG_CNT; p++)
274 M_LLD(rd->argintregs[p], REG_SP, p * 8);
276 for (p = 0; p < FLT_ARG_CNT; p++)
277 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
280 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
285 /* copy argument registers to stack and call trace function */
288 M_LDA(REG_SP, REG_SP, -(2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
289 M_AST(REG_RA, REG_SP, 1 * 8);
291 /* save integer argument registers */
293 for (p = 0; p < md->paramcount && p < INT_ARG_CNT; p++)
294 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
296 /* save and copy float arguments into integer registers */
298 for (p = 0; p < md->paramcount && p < FLT_ARG_CNT; p++) {
299 t = md->paramtypes[p].type;
301 if (IS_FLT_DBL_TYPE(t)) {
302 if (IS_2_WORD_TYPE(t)) {
303 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
304 M_LLD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
307 M_FST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
308 M_ILD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
312 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
316 /* save temporary registers for leaf methods */
318 if (m->isleafmethod) {
319 for (p = 0; p < INT_TMP_CNT; p++)
320 M_LST(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
322 for (p = 0; p < FLT_TMP_CNT; p++)
323 M_DST(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
326 p = dseg_addaddress(cd, m);
327 M_ALD(REG_ITMP1, REG_PV, p);
328 M_AST(REG_ITMP1, REG_SP, 0 * 8);
329 disp = dseg_addaddress(cd, (void *) builtin_trace_args);
330 M_ALD(REG_ITMP3, REG_PV, disp);
331 M_JSR(REG_RA, REG_ITMP3);
334 M_ALD(REG_RA, REG_SP, 1 * 8);
336 /* restore integer argument registers */
338 for (p = 0; p < md->paramcount && p < INT_ARG_CNT; p++)
339 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
341 /* restore float argument registers */
343 for (p = 0; p < md->paramcount && p < FLT_ARG_CNT; p++) {
344 t = md->paramtypes[p].type;
346 if (IS_FLT_DBL_TYPE(t)) {
347 if (IS_2_WORD_TYPE(t)) {
348 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
351 M_FLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
355 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
359 /* restore temporary registers for leaf methods */
361 if (m->isleafmethod) {
362 for (p = 0; p < INT_TMP_CNT; p++)
363 M_LLD(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
365 for (p = 0; p < FLT_TMP_CNT; p++)
366 M_DLD(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
369 M_LDA(REG_SP, REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
374 /* end of header generation */
376 /* walk through all basic blocks */
378 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
380 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
382 if (bptr->flags >= BBREACHED) {
384 /* branch resolving */
387 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
388 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
394 /* copy interface registers to their destination */
399 #if defined(ENABLE_LSRA)
401 while (src != NULL) {
403 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
404 /* d = reg_of_var(m, src, REG_ITMP1); */
405 if (!(src->flags & INMEMORY))
409 M_INTMOVE(REG_ITMP1, d);
410 store_reg_to_var_int(src, d);
416 while (src != NULL) {
418 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
419 d = reg_of_var(rd, src, REG_ITMP1);
420 M_INTMOVE(REG_ITMP1, d);
421 store_reg_to_var_int(src, d);
424 d = reg_of_var(rd, src, REG_IFTMP);
425 if ((src->varkind != STACKVAR)) {
427 if (IS_FLT_DBL_TYPE(s2)) {
428 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
429 s1 = rd->interfaces[len][s2].regoff;
430 M_TFLTMOVE(s2, s1, d);
433 M_DLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
435 store_reg_to_var_flt(src, d);
438 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
439 s1 = rd->interfaces[len][s2].regoff;
443 M_LLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
445 store_reg_to_var_int(src, d);
451 #if defined(ENABLE_LSRA)
454 /* walk through all instructions */
460 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
461 if (iptr->line != currentline) {
462 dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
463 currentline = iptr->line;
466 MCODECHECK(64); /* an instruction usually needs < 64 words */
470 case ICMD_NOP: /* ... ==> ... */
473 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
475 var_to_reg_int(s1, src, REG_ITMP1);
477 codegen_addxnullrefs(cd, mcodeptr);
481 /* constant operations ************************************************/
483 case ICMD_ICONST: /* ... ==> ..., constant */
484 /* op1 = 0, val.i = constant */
486 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
487 ICONST(d, iptr->val.i);
488 store_reg_to_var_int(iptr->dst, d);
491 case ICMD_LCONST: /* ... ==> ..., constant */
492 /* op1 = 0, val.l = constant */
494 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
495 LCONST(d, iptr->val.l);
496 store_reg_to_var_int(iptr->dst, d);
499 case ICMD_FCONST: /* ... ==> ..., constant */
500 /* op1 = 0, val.f = constant */
502 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
503 disp = dseg_addfloat(cd, iptr->val.f);
504 M_FLD(d, REG_PV, disp);
505 store_reg_to_var_flt(iptr->dst, d);
508 case ICMD_DCONST: /* ... ==> ..., constant */
509 /* op1 = 0, val.d = constant */
511 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
512 disp = dseg_adddouble(cd, iptr->val.d);
513 M_DLD(d, REG_PV, disp);
514 store_reg_to_var_flt (iptr->dst, d);
517 case ICMD_ACONST: /* ... ==> ..., constant */
518 /* op1 = 0, val.a = constant */
520 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
522 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
523 disp = dseg_addaddress(cd, iptr->val.a);
525 codegen_addpatchref(cd, mcodeptr,
527 (unresolved_class *) iptr->target, disp);
529 if (opt_showdisassemble) {
533 M_ALD(d, REG_PV, disp);
536 if (iptr->val.a == NULL) {
537 M_INTMOVE(REG_ZERO, d);
539 disp = dseg_addaddress(cd, iptr->val.a);
540 M_ALD(d, REG_PV, disp);
543 store_reg_to_var_int(iptr->dst, d);
547 /* load/store operations **********************************************/
549 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
550 case ICMD_LLOAD: /* op1 = local variable */
553 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
554 if ((iptr->dst->varkind == LOCALVAR) &&
555 (iptr->dst->varnum == iptr->op1))
557 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
558 if (var->flags & INMEMORY) {
559 M_LLD(d, REG_SP, 8 * var->regoff);
561 M_INTMOVE(var->regoff,d);
563 store_reg_to_var_int(iptr->dst, d);
566 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
567 case ICMD_DLOAD: /* op1 = local variable */
569 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
570 if ((iptr->dst->varkind == LOCALVAR) &&
571 (iptr->dst->varnum == iptr->op1))
573 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
575 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
576 if (var->flags & INMEMORY) {
577 M_CCFLD(var->type, t2, d, REG_SP, 8 * var->regoff);
579 M_CCFLTMOVE(var->type, t2, var->regoff, d);
582 store_reg_to_var_flt(iptr->dst, d);
586 case ICMD_ISTORE: /* ..., value ==> ... */
587 case ICMD_LSTORE: /* op1 = local variable */
590 if ((src->varkind == LOCALVAR) &&
591 (src->varnum == iptr->op1))
593 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
594 if (var->flags & INMEMORY) {
595 var_to_reg_int(s1, src, REG_ITMP1);
596 M_LST(s1, REG_SP, 8 * var->regoff);
599 var_to_reg_int(s1, src, var->regoff);
600 M_INTMOVE(s1, var->regoff);
604 case ICMD_FSTORE: /* ..., value ==> ... */
605 case ICMD_DSTORE: /* op1 = local variable */
607 if ((src->varkind == LOCALVAR) &&
608 (src->varnum == iptr->op1))
610 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
612 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
613 if (var->flags & INMEMORY) {
614 var_to_reg_flt(s1, src, REG_FTMP1);
615 M_CCFST(t1, var->type, s1, REG_SP, 8 * var->regoff);
618 var_to_reg_flt(s1, src, var->regoff);
619 M_CCFLTMOVE(t1, var->type, s1, var->regoff);
625 /* pop/dup/swap operations ********************************************/
627 /* attention: double and longs are only one entry in CACAO ICMDs */
629 case ICMD_POP: /* ..., value ==> ... */
630 case ICMD_POP2: /* ..., value, value ==> ... */
633 case ICMD_DUP: /* ..., a ==> ..., a, a */
634 M_COPY(src, iptr->dst);
637 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
639 M_COPY(src, iptr->dst);
640 M_COPY(src->prev, iptr->dst->prev);
641 M_COPY(iptr->dst, iptr->dst->prev->prev);
644 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
646 M_COPY(src, iptr->dst);
647 M_COPY(src->prev, iptr->dst->prev);
648 M_COPY(src->prev->prev, iptr->dst->prev->prev);
649 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
652 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
654 M_COPY(src, iptr->dst);
655 M_COPY(src->prev, iptr->dst->prev);
658 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
660 M_COPY(src, iptr->dst);
661 M_COPY(src->prev, iptr->dst->prev);
662 M_COPY(src->prev->prev, iptr->dst->prev->prev);
663 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
664 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
667 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
669 M_COPY(src, iptr->dst);
670 M_COPY(src->prev, iptr->dst->prev);
671 M_COPY(src->prev->prev, iptr->dst->prev->prev);
672 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
673 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
674 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
677 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
679 M_COPY(src, iptr->dst->prev);
680 M_COPY(src->prev, iptr->dst);
684 /* integer operations *************************************************/
686 case ICMD_INEG: /* ..., value ==> ..., - value */
688 var_to_reg_int(s1, src, REG_ITMP1);
689 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
690 M_ISUB(REG_ZERO, s1, d);
691 store_reg_to_var_int(iptr->dst, d);
694 case ICMD_LNEG: /* ..., value ==> ..., - value */
696 var_to_reg_int(s1, src, REG_ITMP1);
697 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
698 M_LSUB(REG_ZERO, s1, d);
699 store_reg_to_var_int(iptr->dst, d);
702 case ICMD_I2L: /* ..., value ==> ..., value */
704 var_to_reg_int(s1, src, REG_ITMP1);
705 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
707 store_reg_to_var_int(iptr->dst, d);
710 case ICMD_L2I: /* ..., value ==> ..., value */
712 var_to_reg_int(s1, src, REG_ITMP1);
713 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
714 M_ISLL_IMM(s1, 0, d );
715 store_reg_to_var_int(iptr->dst, d);
718 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
720 var_to_reg_int(s1, src, REG_ITMP1);
721 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
722 M_LSLL_IMM(s1, 56, d);
723 M_LSRA_IMM( d, 56, d);
724 store_reg_to_var_int(iptr->dst, d);
727 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
729 var_to_reg_int(s1, src, REG_ITMP1);
730 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
732 store_reg_to_var_int(iptr->dst, d);
735 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
737 var_to_reg_int(s1, src, REG_ITMP1);
738 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
739 M_LSLL_IMM(s1, 48, d);
740 M_LSRA_IMM( d, 48, d);
741 store_reg_to_var_int(iptr->dst, d);
745 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
747 var_to_reg_int(s1, src->prev, REG_ITMP1);
748 var_to_reg_int(s2, src, REG_ITMP2);
749 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
751 store_reg_to_var_int(iptr->dst, d);
754 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
755 /* val.i = constant */
757 var_to_reg_int(s1, src, REG_ITMP1);
758 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
759 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
760 M_IADD_IMM(s1, iptr->val.i, d);
762 ICONST(REG_ITMP2, iptr->val.i);
763 M_IADD(s1, REG_ITMP2, d);
765 store_reg_to_var_int(iptr->dst, d);
768 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
770 var_to_reg_int(s1, src->prev, REG_ITMP1);
771 var_to_reg_int(s2, src, REG_ITMP2);
772 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
774 store_reg_to_var_int(iptr->dst, d);
777 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
778 /* val.l = constant */
780 var_to_reg_int(s1, src, REG_ITMP1);
781 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
782 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
783 M_LADD_IMM(s1, iptr->val.l, d);
785 LCONST(REG_ITMP2, iptr->val.l);
786 M_LADD(s1, REG_ITMP2, d);
788 store_reg_to_var_int(iptr->dst, d);
791 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
793 var_to_reg_int(s1, src->prev, REG_ITMP1);
794 var_to_reg_int(s2, src, REG_ITMP2);
795 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
797 store_reg_to_var_int(iptr->dst, d);
800 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
801 /* val.i = constant */
803 var_to_reg_int(s1, src, REG_ITMP1);
804 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
805 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
806 M_IADD_IMM(s1, -iptr->val.i, d);
808 ICONST(REG_ITMP2, iptr->val.i);
809 M_ISUB(s1, REG_ITMP2, d);
811 store_reg_to_var_int(iptr->dst, d);
814 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
816 var_to_reg_int(s1, src->prev, REG_ITMP1);
817 var_to_reg_int(s2, src, REG_ITMP2);
818 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
820 store_reg_to_var_int(iptr->dst, d);
823 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
824 /* val.l = constant */
826 var_to_reg_int(s1, src, REG_ITMP1);
827 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
828 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
829 M_LADD_IMM(s1, -iptr->val.l, d);
831 LCONST(REG_ITMP2, iptr->val.l);
832 M_LSUB(s1, REG_ITMP2, d);
834 store_reg_to_var_int(iptr->dst, d);
837 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
839 var_to_reg_int(s1, src->prev, REG_ITMP1);
840 var_to_reg_int(s2, src, REG_ITMP2);
841 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
846 store_reg_to_var_int(iptr->dst, d);
849 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
850 /* val.i = constant */
852 var_to_reg_int(s1, src, REG_ITMP1);
853 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
854 ICONST(REG_ITMP2, iptr->val.i);
855 M_IMUL(s1, REG_ITMP2);
859 store_reg_to_var_int(iptr->dst, d);
862 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
864 var_to_reg_int(s1, src->prev, REG_ITMP1);
865 var_to_reg_int(s2, src, REG_ITMP2);
866 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
871 store_reg_to_var_int(iptr->dst, d);
874 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
875 /* val.l = constant */
877 var_to_reg_int(s1, src, REG_ITMP1);
878 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
879 LCONST(REG_ITMP2, iptr->val.l);
880 M_LMUL(s1, REG_ITMP2);
884 store_reg_to_var_int(iptr->dst, d);
887 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
889 var_to_reg_int(s1, src->prev, REG_ITMP1);
890 var_to_reg_int(s2, src, REG_ITMP2);
891 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
897 store_reg_to_var_int(iptr->dst, d);
900 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
902 var_to_reg_int(s1, src->prev, REG_ITMP1);
903 var_to_reg_int(s2, src, REG_ITMP2);
904 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
910 store_reg_to_var_int(iptr->dst, d);
913 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
915 var_to_reg_int(s1, src->prev, REG_ITMP1);
916 var_to_reg_int(s2, src, REG_ITMP2);
917 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
923 store_reg_to_var_int(iptr->dst, d);
926 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
928 var_to_reg_int(s1, src->prev, REG_ITMP1);
929 var_to_reg_int(s2, src, REG_ITMP2);
930 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
936 store_reg_to_var_int(iptr->dst, d);
939 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
940 case ICMD_LDIVPOW2: /* val.i = constant */
942 var_to_reg_int(s1, src, REG_ITMP1);
943 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
944 M_LSRA_IMM(s1, 63, REG_ITMP2);
945 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
946 M_LADD(s1, REG_ITMP2, REG_ITMP2);
947 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
948 store_reg_to_var_int(iptr->dst, d);
951 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
953 var_to_reg_int(s1, src->prev, REG_ITMP1);
954 var_to_reg_int(s2, src, REG_ITMP2);
955 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
957 store_reg_to_var_int(iptr->dst, d);
960 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
961 /* val.i = constant */
963 var_to_reg_int(s1, src, REG_ITMP1);
964 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
965 M_ISLL_IMM(s1, iptr->val.i, d);
966 store_reg_to_var_int(iptr->dst, d);
969 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
971 var_to_reg_int(s1, src->prev, REG_ITMP1);
972 var_to_reg_int(s2, src, REG_ITMP2);
973 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
975 store_reg_to_var_int(iptr->dst, d);
978 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
979 /* val.i = constant */
981 var_to_reg_int(s1, src, REG_ITMP1);
982 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
983 M_ISRA_IMM(s1, iptr->val.i, d);
984 store_reg_to_var_int(iptr->dst, d);
987 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
989 var_to_reg_int(s1, src->prev, REG_ITMP1);
990 var_to_reg_int(s2, src, REG_ITMP2);
991 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
993 store_reg_to_var_int(iptr->dst, d);
996 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
997 /* val.i = constant */
999 var_to_reg_int(s1, src, REG_ITMP1);
1000 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1001 M_ISRL_IMM(s1, iptr->val.i, d);
1002 store_reg_to_var_int(iptr->dst, d);
1005 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1007 var_to_reg_int(s1, src->prev, REG_ITMP1);
1008 var_to_reg_int(s2, src, REG_ITMP2);
1009 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1011 store_reg_to_var_int(iptr->dst, d);
1014 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1015 /* val.i = constant */
1017 var_to_reg_int(s1, src, REG_ITMP1);
1018 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1019 M_LSLL_IMM(s1, iptr->val.i, d);
1020 store_reg_to_var_int(iptr->dst, d);
1023 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1025 var_to_reg_int(s1, src->prev, REG_ITMP1);
1026 var_to_reg_int(s2, src, REG_ITMP2);
1027 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1029 store_reg_to_var_int(iptr->dst, d);
1032 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1033 /* val.i = constant */
1035 var_to_reg_int(s1, src, REG_ITMP1);
1036 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1037 M_LSRA_IMM(s1, iptr->val.i, d);
1038 store_reg_to_var_int(iptr->dst, d);
1041 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1043 var_to_reg_int(s1, src->prev, REG_ITMP1);
1044 var_to_reg_int(s2, src, REG_ITMP2);
1045 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1047 store_reg_to_var_int(iptr->dst, d);
1050 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1051 /* val.i = constant */
1053 var_to_reg_int(s1, src, REG_ITMP1);
1054 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1055 M_LSRL_IMM(s1, iptr->val.i, d);
1056 store_reg_to_var_int(iptr->dst, d);
1059 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1062 var_to_reg_int(s1, src->prev, REG_ITMP1);
1063 var_to_reg_int(s2, src, REG_ITMP2);
1064 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1066 store_reg_to_var_int(iptr->dst, d);
1069 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1070 /* val.i = constant */
1072 var_to_reg_int(s1, src, REG_ITMP1);
1073 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1074 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1075 M_AND_IMM(s1, iptr->val.i, d);
1077 ICONST(REG_ITMP2, iptr->val.i);
1078 M_AND(s1, REG_ITMP2, d);
1080 store_reg_to_var_int(iptr->dst, d);
1083 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1084 /* val.i = constant */
1086 var_to_reg_int(s1, src, REG_ITMP1);
1087 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1089 M_MOV(s1, REG_ITMP1);
1092 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1093 M_AND_IMM(s1, iptr->val.i, d);
1096 M_ISUB(REG_ZERO, s1, d);
1097 M_AND_IMM(d, iptr->val.i, d);
1099 ICONST(REG_ITMP2, iptr->val.i);
1100 M_AND(s1, REG_ITMP2, d);
1103 M_ISUB(REG_ZERO, s1, d);
1104 M_AND(d, REG_ITMP2, d);
1106 M_ISUB(REG_ZERO, d, d);
1107 store_reg_to_var_int(iptr->dst, d);
1110 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1111 /* val.l = constant */
1113 var_to_reg_int(s1, src, REG_ITMP1);
1114 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1115 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1116 M_AND_IMM(s1, iptr->val.l, d);
1118 LCONST(REG_ITMP2, iptr->val.l);
1119 M_AND(s1, REG_ITMP2, d);
1121 store_reg_to_var_int(iptr->dst, d);
1124 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1125 /* val.l = constant */
1127 var_to_reg_int(s1, src, REG_ITMP1);
1128 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1130 M_MOV(s1, REG_ITMP1);
1133 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1134 M_AND_IMM(s1, iptr->val.l, d);
1137 M_LSUB(REG_ZERO, s1, d);
1138 M_AND_IMM(d, iptr->val.l, d);
1140 LCONST(REG_ITMP2, iptr->val.l);
1141 M_AND(s1, REG_ITMP2, d);
1144 M_LSUB(REG_ZERO, s1, d);
1145 M_AND(d, REG_ITMP2, d);
1147 M_LSUB(REG_ZERO, d, d);
1148 store_reg_to_var_int(iptr->dst, d);
1151 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1154 var_to_reg_int(s1, src->prev, REG_ITMP1);
1155 var_to_reg_int(s2, src, REG_ITMP2);
1156 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1158 store_reg_to_var_int(iptr->dst, d);
1161 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1162 /* val.i = constant */
1164 var_to_reg_int(s1, src, REG_ITMP1);
1165 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1166 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1167 M_OR_IMM(s1, iptr->val.i, d);
1169 ICONST(REG_ITMP2, iptr->val.i);
1170 M_OR(s1, REG_ITMP2, d);
1172 store_reg_to_var_int(iptr->dst, d);
1175 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1176 /* val.l = constant */
1178 var_to_reg_int(s1, src, REG_ITMP1);
1179 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1180 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1181 M_OR_IMM(s1, iptr->val.l, d);
1183 LCONST(REG_ITMP2, iptr->val.l);
1184 M_OR(s1, REG_ITMP2, d);
1186 store_reg_to_var_int(iptr->dst, d);
1189 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1192 var_to_reg_int(s1, src->prev, REG_ITMP1);
1193 var_to_reg_int(s2, src, REG_ITMP2);
1194 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1196 store_reg_to_var_int(iptr->dst, d);
1199 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1200 /* val.i = constant */
1202 var_to_reg_int(s1, src, REG_ITMP1);
1203 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1204 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1205 M_XOR_IMM(s1, iptr->val.i, d);
1207 ICONST(REG_ITMP2, iptr->val.i);
1208 M_XOR(s1, REG_ITMP2, d);
1210 store_reg_to_var_int(iptr->dst, d);
1213 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1214 /* val.l = constant */
1216 var_to_reg_int(s1, src, REG_ITMP1);
1217 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1218 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1219 M_XOR_IMM(s1, iptr->val.l, d);
1221 LCONST(REG_ITMP2, iptr->val.l);
1222 M_XOR(s1, REG_ITMP2, d);
1224 store_reg_to_var_int(iptr->dst, d);
1228 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1230 var_to_reg_int(s1, src->prev, REG_ITMP1);
1231 var_to_reg_int(s2, src, REG_ITMP2);
1232 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1233 M_CMPLT(s1, s2, REG_ITMP3);
1234 M_CMPLT(s2, s1, REG_ITMP1);
1235 M_LSUB(REG_ITMP1, REG_ITMP3, d);
1236 store_reg_to_var_int(iptr->dst, d);
1240 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1241 /* op1 = variable, val.i = constant */
1243 var = &(rd->locals[iptr->op1][TYPE_INT]);
1244 if (var->flags & INMEMORY) {
1246 M_LLD(s1, REG_SP, var->regoff * 8);
1249 M_IADD_IMM(s1, iptr->val.i, s1);
1250 if (var->flags & INMEMORY)
1251 M_LST(s1, REG_SP, var->regoff * 8);
1255 /* floating operations ************************************************/
1257 case ICMD_FNEG: /* ..., value ==> ..., - value */
1259 var_to_reg_flt(s1, src, REG_FTMP1);
1260 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1262 store_reg_to_var_flt(iptr->dst, d);
1265 case ICMD_DNEG: /* ..., value ==> ..., - value */
1267 var_to_reg_flt(s1, src, REG_FTMP1);
1268 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1270 store_reg_to_var_flt(iptr->dst, d);
1273 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1275 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1276 var_to_reg_flt(s2, src, REG_FTMP2);
1277 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1279 store_reg_to_var_flt(iptr->dst, d);
1282 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1284 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1285 var_to_reg_flt(s2, src, REG_FTMP2);
1286 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1288 store_reg_to_var_flt(iptr->dst, d);
1291 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1293 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1294 var_to_reg_flt(s2, src, REG_FTMP2);
1295 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1297 store_reg_to_var_flt(iptr->dst, d);
1300 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1302 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1303 var_to_reg_flt(s2, src, REG_FTMP2);
1304 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1306 store_reg_to_var_flt(iptr->dst, d);
1309 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1311 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1312 var_to_reg_flt(s2, src, REG_FTMP2);
1313 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1315 store_reg_to_var_flt(iptr->dst, d);
1318 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1320 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1321 var_to_reg_flt(s2, src, REG_FTMP2);
1322 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1324 store_reg_to_var_flt(iptr->dst, d);
1327 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1329 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1330 var_to_reg_flt(s2, src, REG_FTMP2);
1331 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1333 store_reg_to_var_flt(iptr->dst, d);
1336 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1338 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1339 var_to_reg_flt(s2, src, REG_FTMP2);
1340 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1342 store_reg_to_var_flt(iptr->dst, d);
1346 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1348 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1349 var_to_reg_flt(s2, src, REG_FTMP2);
1350 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1351 M_FDIV(s1,s2, REG_FTMP3);
1352 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1353 M_CVTLF(REG_FTMP3, REG_FTMP3);
1354 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1355 M_FSUB(s1, REG_FTMP3, d);
1356 store_reg_to_var_flt(iptr->dst, d);
1359 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1361 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1362 var_to_reg_flt(s2, src, REG_FTMP2);
1363 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1364 M_DDIV(s1,s2, REG_FTMP3);
1365 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1366 M_CVTLD(REG_FTMP3, REG_FTMP3);
1367 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1368 M_DSUB(s1, REG_FTMP3, d);
1369 store_reg_to_var_flt(iptr->dst, d);
1373 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1375 var_to_reg_int(s1, src, REG_ITMP1);
1376 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1379 store_reg_to_var_flt(iptr->dst, d);
1382 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1384 var_to_reg_int(s1, src, REG_ITMP1);
1385 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1388 store_reg_to_var_flt(iptr->dst, d);
1392 /* XXX these do not work correctly */
1394 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1396 var_to_reg_flt(s1, src, REG_FTMP1);
1397 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1398 M_TRUNCFI(s1, REG_FTMP1);
1399 M_MOVDI(REG_FTMP1, d);
1401 store_reg_to_var_int(iptr->dst, d);
1404 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1406 var_to_reg_flt(s1, src, REG_FTMP1);
1407 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1408 M_TRUNCDI(s1, REG_FTMP1);
1409 M_MOVDI(REG_FTMP1, d);
1411 store_reg_to_var_int(iptr->dst, d);
1414 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1416 var_to_reg_flt(s1, src, REG_FTMP1);
1417 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1418 M_TRUNCFL(s1, REG_FTMP1);
1419 M_MOVDL(REG_FTMP1, d);
1421 store_reg_to_var_int(iptr->dst, d);
1424 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1426 var_to_reg_flt(s1, src, REG_FTMP1);
1427 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1428 M_TRUNCDL(s1, REG_FTMP1);
1429 M_MOVDL(REG_FTMP1, d);
1431 store_reg_to_var_int(iptr->dst, d);
1435 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1437 var_to_reg_flt(s1, src, REG_FTMP1);
1438 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1440 store_reg_to_var_flt(iptr->dst, d);
1443 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1445 var_to_reg_flt(s1, src, REG_FTMP1);
1446 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1448 store_reg_to_var_flt(iptr->dst, d);
1451 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1453 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1454 var_to_reg_flt(s2, src, REG_FTMP2);
1455 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1458 M_LADD_IMM(REG_ZERO, 1, d);
1462 M_LSUB_IMM(REG_ZERO, 1, d);
1463 M_CMOVT(REG_ZERO, d);
1464 store_reg_to_var_int(iptr->dst, d);
1467 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1469 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1470 var_to_reg_flt(s2, src, REG_FTMP2);
1471 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1474 M_LADD_IMM(REG_ZERO, 1, d);
1478 M_LSUB_IMM(REG_ZERO, 1, d);
1479 M_CMOVT(REG_ZERO, d);
1480 store_reg_to_var_int(iptr->dst, d);
1483 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1485 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1486 var_to_reg_flt(s2, src, REG_FTMP2);
1487 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1490 M_LSUB_IMM(REG_ZERO, 1, d);
1494 M_LADD_IMM(REG_ZERO, 1, d);
1495 M_CMOVT(REG_ZERO, d);
1496 store_reg_to_var_int(iptr->dst, d);
1499 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1501 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1502 var_to_reg_flt(s2, src, REG_FTMP2);
1503 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1506 M_LSUB_IMM(REG_ZERO, 1, d);
1510 M_LADD_IMM(REG_ZERO, 1, d);
1511 M_CMOVT(REG_ZERO, d);
1512 store_reg_to_var_int(iptr->dst, d);
1516 /* memory operations **************************************************/
1518 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1520 var_to_reg_int(s1, src, REG_ITMP1);
1521 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1522 gen_nullptr_check(s1);
1523 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1524 store_reg_to_var_int(iptr->dst, d);
1527 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1529 var_to_reg_int(s1, src->prev, REG_ITMP1);
1530 var_to_reg_int(s2, src, REG_ITMP2);
1531 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1532 if (iptr->op1 == 0) {
1533 gen_nullptr_check(s1);
1536 M_AADD(s2, s1, REG_ITMP3);
1537 M_BLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1538 store_reg_to_var_int(iptr->dst, d);
1541 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1543 var_to_reg_int(s1, src->prev, REG_ITMP1);
1544 var_to_reg_int(s2, src, REG_ITMP2);
1545 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1546 if (iptr->op1 == 0) {
1547 gen_nullptr_check(s1);
1550 M_AADD(s2, s1, REG_ITMP3);
1551 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1552 M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1553 store_reg_to_var_int(iptr->dst, d);
1556 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1558 var_to_reg_int(s1, src->prev, REG_ITMP1);
1559 var_to_reg_int(s2, src, REG_ITMP2);
1560 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1561 if (iptr->op1 == 0) {
1562 gen_nullptr_check(s1);
1565 M_AADD(s2, s1, REG_ITMP3);
1566 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1567 M_SLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1568 store_reg_to_var_int(iptr->dst, d);
1571 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1573 var_to_reg_int(s1, src->prev, REG_ITMP1);
1574 var_to_reg_int(s2, src, REG_ITMP2);
1575 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1576 if (iptr->op1 == 0) {
1577 gen_nullptr_check(s1);
1580 M_ASLL_IMM(s2, 2, REG_ITMP3);
1581 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1582 M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
1583 store_reg_to_var_int(iptr->dst, d);
1586 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1588 var_to_reg_int(s1, src->prev, REG_ITMP1);
1589 var_to_reg_int(s2, src, REG_ITMP2);
1590 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1591 if (iptr->op1 == 0) {
1592 gen_nullptr_check(s1);
1595 M_ASLL_IMM(s2, 3, REG_ITMP3);
1596 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1597 M_LLD(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
1598 store_reg_to_var_int(iptr->dst, d);
1601 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1603 var_to_reg_int(s1, src->prev, REG_ITMP1);
1604 var_to_reg_int(s2, src, REG_ITMP2);
1605 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1606 if (iptr->op1 == 0) {
1607 gen_nullptr_check(s1);
1610 M_ASLL_IMM(s2, 2, REG_ITMP3);
1611 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1612 M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
1613 store_reg_to_var_flt(iptr->dst, d);
1616 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1618 var_to_reg_int(s1, src->prev, REG_ITMP1);
1619 var_to_reg_int(s2, src, REG_ITMP2);
1620 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1621 if (iptr->op1 == 0) {
1622 gen_nullptr_check(s1);
1625 M_ASLL_IMM(s2, 3, REG_ITMP3);
1626 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1627 M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
1628 store_reg_to_var_flt(iptr->dst, d);
1631 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1633 var_to_reg_int(s1, src->prev, REG_ITMP1);
1634 var_to_reg_int(s2, src, REG_ITMP2);
1635 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1636 if (iptr->op1 == 0) {
1637 gen_nullptr_check(s1);
1640 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1641 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1642 M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
1643 store_reg_to_var_int(iptr->dst, d);
1647 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1649 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1650 var_to_reg_int(s2, src->prev, REG_ITMP2);
1651 if (iptr->op1 == 0) {
1652 gen_nullptr_check(s1);
1655 M_AADD(s2, s1, REG_ITMP1);
1656 var_to_reg_int(s3, src, REG_ITMP3);
1657 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1660 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1661 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1663 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1664 var_to_reg_int(s2, src->prev, REG_ITMP2);
1665 if (iptr->op1 == 0) {
1666 gen_nullptr_check(s1);
1669 M_AADD(s2, s1, REG_ITMP1);
1670 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1671 var_to_reg_int(s3, src, REG_ITMP3);
1672 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1675 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1677 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1678 var_to_reg_int(s2, src->prev, REG_ITMP2);
1679 if (iptr->op1 == 0) {
1680 gen_nullptr_check(s1);
1683 M_ASLL_IMM(s2, 2, REG_ITMP2);
1684 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1685 var_to_reg_int(s3, src, REG_ITMP3);
1686 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1689 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1691 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1692 var_to_reg_int(s2, src->prev, REG_ITMP2);
1693 if (iptr->op1 == 0) {
1694 gen_nullptr_check(s1);
1697 M_ASLL_IMM(s2, 3, REG_ITMP2);
1698 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1699 var_to_reg_int(s3, src, REG_ITMP3);
1700 M_LST_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1703 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1705 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1706 var_to_reg_int(s2, src->prev, REG_ITMP2);
1707 if (iptr->op1 == 0) {
1708 gen_nullptr_check(s1);
1711 M_ASLL_IMM(s2, 2, REG_ITMP2);
1712 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1713 var_to_reg_flt(s3, src, REG_FTMP1);
1714 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1717 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1719 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1720 var_to_reg_int(s2, src->prev, REG_ITMP2);
1721 if (iptr->op1 == 0) {
1722 gen_nullptr_check(s1);
1725 M_ASLL_IMM(s2, 3, REG_ITMP2);
1726 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1727 var_to_reg_flt(s3, src, REG_FTMP1);
1728 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1732 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1734 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1735 var_to_reg_int(s2, src->prev, REG_ITMP2);
1736 if (iptr->op1 == 0) {
1737 gen_nullptr_check(s1);
1740 var_to_reg_int(s3, src, REG_ITMP3);
1742 M_MOV(s1, rd->argintregs[0]);
1743 M_MOV(s3, rd->argintregs[1]);
1744 disp = dseg_addaddress(cd, BUILTIN_canstore);
1745 M_ALD(REG_ITMP3, REG_PV, disp);
1746 M_JSR(REG_RA, REG_ITMP3);
1749 M_BEQZ(REG_RESULT, 0);
1750 codegen_addxstorerefs(cd, mcodeptr);
1753 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1754 var_to_reg_int(s2, src->prev, REG_ITMP2);
1755 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1756 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1757 var_to_reg_int(s3, src, REG_ITMP3);
1758 M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1762 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1764 var_to_reg_int(s1, src->prev, REG_ITMP1);
1765 var_to_reg_int(s2, src, REG_ITMP2);
1766 if (iptr->op1 == 0) {
1767 gen_nullptr_check(s1);
1770 M_AADD(s2, s1, REG_ITMP1);
1771 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1774 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1775 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1777 var_to_reg_int(s1, src->prev, REG_ITMP1);
1778 var_to_reg_int(s2, src, REG_ITMP2);
1779 if (iptr->op1 == 0) {
1780 gen_nullptr_check(s1);
1783 M_AADD(s2, s1, REG_ITMP1);
1784 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1785 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
1788 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1790 var_to_reg_int(s1, src->prev, REG_ITMP1);
1791 var_to_reg_int(s2, src, REG_ITMP2);
1792 if (iptr->op1 == 0) {
1793 gen_nullptr_check(s1);
1796 M_ASLL_IMM(s2, 2, REG_ITMP2);
1797 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1798 M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1801 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1803 var_to_reg_int(s1, src->prev, REG_ITMP1);
1804 var_to_reg_int(s2, src, REG_ITMP2);
1805 if (iptr->op1 == 0) {
1806 gen_nullptr_check(s1);
1809 M_ASLL_IMM(s2, 3, REG_ITMP2);
1810 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1811 M_LST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1814 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1816 var_to_reg_int(s1, src->prev, REG_ITMP1);
1817 var_to_reg_int(s2, src, REG_ITMP2);
1818 if (iptr->op1 == 0) {
1819 gen_nullptr_check(s1);
1822 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1823 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1824 M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1828 case ICMD_GETSTATIC: /* ... ==> ..., value */
1829 /* op1 = type, val.a = field address */
1832 disp = dseg_addaddress(cd, NULL);
1834 codegen_addpatchref(cd, mcodeptr,
1835 PATCHER_get_putstatic,
1836 (unresolved_field *) iptr->target, disp);
1838 if (opt_showdisassemble) {
1843 fieldinfo *fi = iptr->val.a;
1845 disp = dseg_addaddress(cd, &(fi->value));
1847 if (!(fi->class->state & CLASS_INITIALIZED)) {
1848 codegen_addpatchref(cd, mcodeptr,
1849 PATCHER_clinit, fi->class, 0);
1851 if (opt_showdisassemble) {
1857 M_ALD(REG_ITMP1, REG_PV, disp);
1858 switch (iptr->op1) {
1860 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1861 M_ILD_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_LLD_INTERN(d, REG_ITMP1, 0);
1867 store_reg_to_var_int(iptr->dst, d);
1870 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1871 M_ALD_INTERN(d, REG_ITMP1, 0);
1872 store_reg_to_var_int(iptr->dst, d);
1875 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1876 M_FLD_INTERN(d, REG_ITMP1, 0);
1877 store_reg_to_var_flt(iptr->dst, d);
1880 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1881 M_DLD_INTERN(d, REG_ITMP1, 0);
1882 store_reg_to_var_flt(iptr->dst, d);
1887 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1888 /* op1 = type, val.a = field address */
1891 disp = dseg_addaddress(cd, NULL);
1893 codegen_addpatchref(cd, mcodeptr,
1894 PATCHER_get_putstatic,
1895 (unresolved_field *) iptr->target, disp);
1897 if (opt_showdisassemble) {
1902 fieldinfo *fi = iptr->val.a;
1904 disp = dseg_addaddress(cd, &(fi->value));
1906 if (!(fi->class->state & CLASS_INITIALIZED)) {
1907 codegen_addpatchref(cd, mcodeptr,
1908 PATCHER_clinit, fi->class, 0);
1910 if (opt_showdisassemble) {
1916 M_ALD(REG_ITMP1, REG_PV, disp);
1917 switch (iptr->op1) {
1919 var_to_reg_int(s2, src, REG_ITMP2);
1920 M_IST_INTERN(s2, REG_ITMP1, 0);
1923 var_to_reg_int(s2, src, REG_ITMP2);
1924 M_LST_INTERN(s2, REG_ITMP1, 0);
1927 var_to_reg_int(s2, src, REG_ITMP2);
1928 M_AST_INTERN(s2, REG_ITMP1, 0);
1931 var_to_reg_flt(s2, src, REG_FTMP2);
1932 M_FST_INTERN(s2, REG_ITMP1, 0);
1935 var_to_reg_flt(s2, src, REG_FTMP2);
1936 M_DST_INTERN(s2, REG_ITMP1, 0);
1941 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1942 /* val = value (in current instruction) */
1943 /* op1 = type, val.a = field address (in */
1944 /* following NOP) */
1946 if (!iptr[1].val.a) {
1947 disp = dseg_addaddress(cd, NULL);
1949 codegen_addpatchref(cd, mcodeptr,
1950 PATCHER_get_putstatic,
1951 (unresolved_field *) iptr[1].target, disp);
1953 if (opt_showdisassemble) {
1958 fieldinfo *fi = iptr[1].val.a;
1960 disp = dseg_addaddress(cd, &(fi->value));
1962 if (!(fi->class->state & CLASS_INITIALIZED)) {
1963 codegen_addpatchref(cd, mcodeptr,
1964 PATCHER_clinit, fi->class, 0);
1966 if (opt_showdisassemble) {
1972 M_ALD(REG_ITMP1, REG_PV, disp);
1973 switch (iptr->op1) {
1975 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1978 M_LST_INTERN(REG_ZERO, REG_ITMP1, 0);
1981 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1984 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1987 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1993 case ICMD_GETFIELD: /* ... ==> ..., value */
1994 /* op1 = type, val.i = field offset */
1996 var_to_reg_int(s1, src, REG_ITMP1);
1997 gen_nullptr_check(s1);
2000 codegen_addpatchref(cd, mcodeptr,
2001 PATCHER_get_putfield,
2002 (unresolved_field *) iptr->target, 0);
2004 if (opt_showdisassemble) {
2011 a = ((fieldinfo *) (iptr->val.a))->offset;
2014 switch (iptr->op1) {
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_ITMP2);
2028 store_reg_to_var_int(iptr->dst, d);
2031 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2033 store_reg_to_var_flt(iptr->dst, d);
2036 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2038 store_reg_to_var_flt(iptr->dst, d);
2043 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2044 /* op1 = type, val.a = field address */
2046 var_to_reg_int(s1, src->prev, REG_ITMP1);
2047 gen_nullptr_check(s1);
2049 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2050 var_to_reg_int(s2, src, REG_ITMP2);
2052 var_to_reg_flt(s2, src, REG_FTMP2);
2056 codegen_addpatchref(cd, mcodeptr,
2057 PATCHER_get_putfield,
2058 (unresolved_field *) iptr->target, 0);
2060 if (opt_showdisassemble) {
2067 a = ((fieldinfo *) (iptr->val.a))->offset;
2070 switch (iptr->op1) {
2089 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2090 /* val = value (in current instruction) */
2091 /* op1 = type, val.a = field address (in */
2092 /* following NOP) */
2094 var_to_reg_int(s1, src, REG_ITMP1);
2095 gen_nullptr_check(s1);
2097 if (!iptr[1].val.a) {
2098 codegen_addpatchref(cd, mcodeptr,
2099 PATCHER_get_putfield,
2100 (unresolved_field *) iptr[1].target, 0);
2102 if (opt_showdisassemble) {
2109 a = ((fieldinfo *) (iptr[1].val.a))->offset;
2112 switch (iptr[1].op1) {
2114 M_IST(REG_ZERO, s1, a);
2117 M_LST(REG_ZERO, s1, a);
2120 M_AST(REG_ZERO, s1, a);
2123 M_FST(REG_ZERO, s1, a);
2126 M_DST(REG_ZERO, s1, a);
2132 /* branch operations **************************************************/
2134 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2136 var_to_reg_int(s1, src, REG_ITMP1);
2137 M_INTMOVE(s1, REG_ITMP1_XPTR);
2139 #ifdef ENABLE_VERIFIER
2141 codegen_addpatchref(cd, mcodeptr,
2142 PATCHER_athrow_areturn,
2143 (unresolved_class *) iptr->val.a, 0);
2145 if (opt_showdisassemble) {
2149 #endif /* ENABLE_VERIFIER */
2151 disp = dseg_addaddress(cd, asm_handle_exception);
2152 M_ALD(REG_ITMP2, REG_PV, disp);
2153 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2155 M_NOP; /* nop ensures that XPC is less than the end */
2156 /* of basic block */
2160 case ICMD_GOTO: /* ... ==> ... */
2161 /* op1 = target JavaVM pc */
2163 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2168 case ICMD_JSR: /* ... ==> ... */
2169 /* op1 = target JavaVM pc */
2171 dseg_addtarget(cd, (basicblock *) iptr->target);
2172 M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
2173 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2177 case ICMD_RET: /* ... ==> ... */
2178 /* op1 = local variable */
2179 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2180 if (var->flags & INMEMORY) {
2181 M_ALD(REG_ITMP1, REG_SP, var->regoff * 8);
2189 case ICMD_IFNULL: /* ..., value ==> ... */
2190 /* op1 = target JavaVM pc */
2192 var_to_reg_int(s1, src, REG_ITMP1);
2194 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2198 case ICMD_IFNONNULL: /* ..., value ==> ... */
2199 /* op1 = target JavaVM pc */
2201 var_to_reg_int(s1, src, REG_ITMP1);
2203 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2207 case ICMD_IFEQ: /* ..., value ==> ... */
2208 /* op1 = target JavaVM pc, val.i = constant */
2210 var_to_reg_int(s1, src, REG_ITMP1);
2211 if (iptr->val.i == 0) {
2214 ICONST(REG_ITMP2, iptr->val.i);
2215 M_BEQ(s1, REG_ITMP2, 0);
2217 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2221 case ICMD_IFLT: /* ..., value ==> ... */
2222 /* op1 = target JavaVM pc, val.i = constant */
2224 var_to_reg_int(s1, src, REG_ITMP1);
2225 if (iptr->val.i == 0) {
2228 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2229 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2231 ICONST(REG_ITMP2, iptr->val.i);
2232 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2234 M_BNEZ(REG_ITMP1, 0);
2236 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2240 case ICMD_IFLE: /* ..., value ==> ... */
2241 /* op1 = target JavaVM pc, val.i = constant */
2243 var_to_reg_int(s1, src, REG_ITMP1);
2244 if (iptr->val.i == 0) {
2248 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2249 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2250 M_BNEZ(REG_ITMP1, 0);
2253 ICONST(REG_ITMP2, iptr->val.i);
2254 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2255 M_BEQZ(REG_ITMP1, 0);
2258 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2262 case ICMD_IFNE: /* ..., value ==> ... */
2263 /* op1 = target JavaVM pc, val.i = constant */
2265 var_to_reg_int(s1, src, REG_ITMP1);
2266 if (iptr->val.i == 0) {
2270 ICONST(REG_ITMP2, iptr->val.i);
2271 M_BNE(s1, REG_ITMP2, 0);
2273 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2277 case ICMD_IFGT: /* ..., value ==> ... */
2278 /* op1 = target JavaVM pc, val.i = constant */
2280 var_to_reg_int(s1, src, REG_ITMP1);
2281 if (iptr->val.i == 0) {
2285 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2286 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2287 M_BEQZ(REG_ITMP1, 0);
2290 ICONST(REG_ITMP2, iptr->val.i);
2291 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2292 M_BNEZ(REG_ITMP1, 0);
2295 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2299 case ICMD_IFGE: /* ..., value ==> ... */
2300 /* op1 = target JavaVM pc, val.i = constant */
2302 var_to_reg_int(s1, src, REG_ITMP1);
2303 if (iptr->val.i == 0) {
2307 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2308 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2311 ICONST(REG_ITMP2, iptr->val.i);
2312 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2314 M_BEQZ(REG_ITMP1, 0);
2316 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2320 case ICMD_IF_LEQ: /* ..., value ==> ... */
2321 /* op1 = target JavaVM pc, val.l = constant */
2323 var_to_reg_int(s1, src, REG_ITMP1);
2324 if (iptr->val.l == 0) {
2328 LCONST(REG_ITMP2, iptr->val.l);
2329 M_BEQ(s1, REG_ITMP2, 0);
2331 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2335 case ICMD_IF_LLT: /* ..., value ==> ... */
2336 /* op1 = target JavaVM pc, val.l = constant */
2338 var_to_reg_int(s1, src, REG_ITMP1);
2339 if (iptr->val.l == 0) {
2343 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2344 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2347 LCONST(REG_ITMP2, iptr->val.l);
2348 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2350 M_BNEZ(REG_ITMP1, 0);
2352 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2356 case ICMD_IF_LLE: /* ..., value ==> ... */
2357 /* op1 = target JavaVM pc, val.l = constant */
2359 var_to_reg_int(s1, src, REG_ITMP1);
2360 if (iptr->val.l == 0) {
2364 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2365 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2366 M_BNEZ(REG_ITMP1, 0);
2369 LCONST(REG_ITMP2, iptr->val.l);
2370 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2371 M_BEQZ(REG_ITMP1, 0);
2374 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2378 case ICMD_IF_LNE: /* ..., value ==> ... */
2379 /* op1 = target JavaVM pc, val.l = constant */
2381 var_to_reg_int(s1, src, REG_ITMP1);
2382 if (iptr->val.l == 0) {
2386 LCONST(REG_ITMP2, iptr->val.l);
2387 M_BNE(s1, REG_ITMP2, 0);
2389 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2393 case ICMD_IF_LGT: /* ..., value ==> ... */
2394 /* op1 = target JavaVM pc, val.l = constant */
2396 var_to_reg_int(s1, src, REG_ITMP1);
2397 if (iptr->val.l == 0) {
2401 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2402 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2403 M_BEQZ(REG_ITMP1, 0);
2406 LCONST(REG_ITMP2, iptr->val.l);
2407 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2408 M_BNEZ(REG_ITMP1, 0);
2411 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2415 case ICMD_IF_LGE: /* ..., value ==> ... */
2416 /* op1 = target JavaVM pc, val.l = constant */
2418 var_to_reg_int(s1, src, REG_ITMP1);
2419 if (iptr->val.l == 0) {
2423 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2424 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2427 LCONST(REG_ITMP2, iptr->val.l);
2428 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2430 M_BEQZ(REG_ITMP1, 0);
2432 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2436 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2437 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2438 case ICMD_IF_ACMPEQ:
2440 var_to_reg_int(s1, src->prev, REG_ITMP1);
2441 var_to_reg_int(s2, src, REG_ITMP2);
2443 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2447 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2448 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2449 case ICMD_IF_ACMPNE:
2451 var_to_reg_int(s1, src->prev, REG_ITMP1);
2452 var_to_reg_int(s2, src, REG_ITMP2);
2454 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2458 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2459 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2461 var_to_reg_int(s1, src->prev, REG_ITMP1);
2462 var_to_reg_int(s2, src, REG_ITMP2);
2463 M_CMPLT(s1, s2, REG_ITMP1);
2464 M_BNEZ(REG_ITMP1, 0);
2465 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2469 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2470 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2472 var_to_reg_int(s1, src->prev, REG_ITMP1);
2473 var_to_reg_int(s2, src, REG_ITMP2);
2474 M_CMPGT(s1, s2, REG_ITMP1);
2475 M_BNEZ(REG_ITMP1, 0);
2476 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2480 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2481 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2483 var_to_reg_int(s1, src->prev, REG_ITMP1);
2484 var_to_reg_int(s2, src, REG_ITMP2);
2485 M_CMPGT(s1, s2, REG_ITMP1);
2486 M_BEQZ(REG_ITMP1, 0);
2487 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2491 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2492 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2494 var_to_reg_int(s1, src->prev, REG_ITMP1);
2495 var_to_reg_int(s2, src, REG_ITMP2);
2496 M_CMPLT(s1, s2, REG_ITMP1);
2497 M_BEQZ(REG_ITMP1, 0);
2498 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2502 #ifdef CONDITIONAL_LOADCONST
2503 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2505 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2508 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2509 /* val.i = constant */
2511 var_to_reg_int(s1, src, REG_ITMP1);
2512 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2514 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2515 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2516 M_CMPEQ(s1, REG_ZERO, d);
2517 store_reg_to_var_int(iptr->dst, d);
2520 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2521 M_CMPEQ(s1, REG_ZERO, d);
2523 store_reg_to_var_int(iptr->dst, d);
2527 M_MOV(s1, REG_ITMP1);
2530 ICONST(d, iptr[1].val.i);
2532 if ((s3 >= 0) && (s3 <= 255)) {
2533 M_CMOVEQ_IMM(s1, s3, d);
2535 ICONST(REG_ITMP3, s3);
2536 M_CMOVEQ(s1, REG_ITMP3, d);
2538 store_reg_to_var_int(iptr->dst, d);
2541 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2542 /* val.i = constant */
2544 var_to_reg_int(s1, src, REG_ITMP1);
2545 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2547 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2548 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2549 M_CMPEQ(s1, REG_ZERO, d);
2550 store_reg_to_var_int(iptr->dst, d);
2553 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2554 M_CMPEQ(s1, REG_ZERO, d);
2556 store_reg_to_var_int(iptr->dst, d);
2560 M_MOV(s1, REG_ITMP1);
2563 ICONST(d, iptr[1].val.i);
2565 if ((s3 >= 0) && (s3 <= 255)) {
2566 M_CMOVNE_IMM(s1, s3, d);
2568 ICONST(REG_ITMP3, s3);
2569 M_CMOVNE(s1, REG_ITMP3, d);
2571 store_reg_to_var_int(iptr->dst, d);
2574 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2575 /* val.i = constant */
2577 var_to_reg_int(s1, src, REG_ITMP1);
2578 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2580 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2581 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2582 M_CMPLT(s1, REG_ZERO, d);
2583 store_reg_to_var_int(iptr->dst, d);
2586 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2587 M_CMPLE(REG_ZERO, s1, d);
2588 store_reg_to_var_int(iptr->dst, d);
2592 M_MOV(s1, REG_ITMP1);
2595 ICONST(d, iptr[1].val.i);
2597 if ((s3 >= 0) && (s3 <= 255)) {
2598 M_CMOVLT_IMM(s1, s3, d);
2600 ICONST(REG_ITMP3, s3);
2601 M_CMOVLT(s1, REG_ITMP3, d);
2603 store_reg_to_var_int(iptr->dst, d);
2606 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2607 /* val.i = constant */
2609 var_to_reg_int(s1, src, REG_ITMP1);
2610 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2612 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2613 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2614 M_CMPLE(REG_ZERO, s1, d);
2615 store_reg_to_var_int(iptr->dst, d);
2618 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2619 M_CMPLT(s1, REG_ZERO, d);
2620 store_reg_to_var_int(iptr->dst, d);
2624 M_MOV(s1, REG_ITMP1);
2627 ICONST(d, iptr[1].val.i);
2629 if ((s3 >= 0) && (s3 <= 255)) {
2630 M_CMOVGE_IMM(s1, s3, d);
2632 ICONST(REG_ITMP3, s3);
2633 M_CMOVGE(s1, REG_ITMP3, d);
2635 store_reg_to_var_int(iptr->dst, d);
2638 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2639 /* val.i = constant */
2641 var_to_reg_int(s1, src, REG_ITMP1);
2642 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2644 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2645 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2646 M_CMPLT(REG_ZERO, s1, d);
2647 store_reg_to_var_int(iptr->dst, d);
2650 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2651 M_CMPLE(s1, REG_ZERO, d);
2652 store_reg_to_var_int(iptr->dst, d);
2656 M_MOV(s1, REG_ITMP1);
2659 ICONST(d, iptr[1].val.i);
2661 if ((s3 >= 0) && (s3 <= 255)) {
2662 M_CMOVGT_IMM(s1, s3, d);
2664 ICONST(REG_ITMP3, s3);
2665 M_CMOVGT(s1, REG_ITMP3, d);
2667 store_reg_to_var_int(iptr->dst, d);
2670 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2671 /* val.i = constant */
2673 var_to_reg_int(s1, src, REG_ITMP1);
2674 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2676 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2677 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2678 M_CMPLE(s1, REG_ZERO, d);
2679 store_reg_to_var_int(iptr->dst, d);
2682 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2683 M_CMPLT(REG_ZERO, s1, d);
2684 store_reg_to_var_int(iptr->dst, d);
2688 M_MOV(s1, REG_ITMP1);
2691 ICONST(d, iptr[1].val.i);
2693 if ((s3 >= 0) && (s3 <= 255)) {
2694 M_CMOVLE_IMM(s1, s3, d);
2696 ICONST(REG_ITMP3, s3);
2697 M_CMOVLE(s1, REG_ITMP3, d);
2699 store_reg_to_var_int(iptr->dst, d);
2704 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2707 var_to_reg_int(s1, src, REG_RESULT);
2708 M_INTMOVE(s1, REG_RESULT);
2709 goto nowperformreturn;
2711 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2713 var_to_reg_int(s1, src, REG_RESULT);
2714 M_INTMOVE(s1, REG_RESULT);
2716 #ifdef ENABLE_VERIFIER
2718 codegen_addpatchref(cd, mcodeptr,
2719 PATCHER_athrow_areturn,
2720 (unresolved_class *) iptr->val.a, 0);
2722 if (opt_showdisassemble) {
2726 #endif /* ENABLE_VERIFIER */
2727 goto nowperformreturn;
2729 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2731 var_to_reg_flt(s1, src, REG_FRESULT);
2733 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2734 M_TFLTMOVE(t, s1, REG_FRESULT);
2736 goto nowperformreturn;
2738 case ICMD_RETURN: /* ... ==> ... */
2744 p = parentargs_base;
2746 /* call trace function */
2749 M_LDA(REG_SP, REG_SP, -3 * 8);
2750 M_LST(REG_RA, REG_SP, 0 * 8);
2751 M_LST(REG_RESULT, REG_SP, 1 * 8);
2752 M_DST(REG_FRESULT, REG_SP, 2 * 8);
2754 disp = dseg_addaddress(cd, m);
2755 M_ALD(rd->argintregs[0], REG_PV, disp);
2756 M_MOV(REG_RESULT, rd->argintregs[1]);
2757 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2758 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
2760 disp = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2761 M_ALD(REG_ITMP3, REG_PV, disp);
2762 M_JSR(REG_RA, REG_ITMP3);
2765 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
2766 M_LLD(REG_RESULT, REG_SP, 1 * 8);
2767 M_LLD(REG_RA, REG_SP, 0 * 8);
2768 M_LDA(REG_SP, REG_SP, 3 * 8);
2771 #if defined(USE_THREADS)
2772 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2773 disp = dseg_addaddress(cd, (void *) builtin_monitorexit);
2774 M_ALD(REG_ITMP3, REG_PV, disp);
2776 /* we need to save the proper return value */
2778 switch (iptr->opc) {
2782 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2783 M_JSR(REG_RA, REG_ITMP3);
2784 M_LST(REG_RESULT, REG_SP, rd->memuse * 8); /* delay slot */
2788 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2789 M_JSR(REG_RA, REG_ITMP3);
2790 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8); /* delay slot */
2793 M_JSR(REG_RA, REG_ITMP3);
2794 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8); /* delay*/
2798 /* and now restore the proper return value */
2800 switch (iptr->opc) {
2804 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
2808 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
2814 /* restore return address */
2816 if (!m->isleafmethod) {
2817 p--; M_ALD(REG_RA, REG_SP, p * 8);
2820 /* restore saved registers */
2822 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2823 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
2825 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2826 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2829 /* deallocate stack and return */
2831 if (parentargs_base) {
2834 disp = parentargs_base * 8;
2835 lo = (short) (disp);
2836 hi = (short) (((disp) - lo) >> 16);
2840 M_LADD_IMM(REG_SP, lo, REG_SP); /* delay slot */
2842 M_LUI(REG_ITMP3,hi);
2843 M_LADD_IMM(REG_ITMP3,lo,REG_ITMP3);
2845 M_LADD(REG_ITMP3,REG_SP,REG_SP); /* delay slot */
2858 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2863 tptr = (void **) iptr->target;
2865 s4ptr = iptr->val.a;
2866 l = s4ptr[1]; /* low */
2867 i = s4ptr[2]; /* high */
2869 var_to_reg_int(s1, src, REG_ITMP1);
2871 {M_INTMOVE(s1, REG_ITMP1);}
2872 else if (l <= 32768) {
2873 M_IADD_IMM(s1, -l, REG_ITMP1);
2876 ICONST(REG_ITMP2, l);
2877 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2883 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
2884 M_BEQZ(REG_ITMP2, 0);
2885 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2886 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
2888 /* build jump table top down and use address of lowest entry */
2890 /* s4ptr += 3 + i; */
2894 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2895 dseg_addtarget(cd, (basicblock *) tptr[0]);
2900 /* length of dataseg after last dseg_addtarget is used by load */
2902 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2903 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2910 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2912 s4 i, /*l, */val, *s4ptr;
2915 tptr = (void **) iptr->target;
2917 s4ptr = iptr->val.a;
2918 /*l = s4ptr[0];*/ /* default */
2919 i = s4ptr[1]; /* count */
2921 MCODECHECK((i<<2)+8);
2922 var_to_reg_int(s1, src, REG_ITMP1);
2928 ICONST(REG_ITMP2, val);
2929 M_BEQ(s1, REG_ITMP2, 0);
2930 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2935 tptr = (void **) iptr->target;
2936 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2943 case ICMD_BUILTIN: /* ..., arg1 ==> ... */
2944 /* op1 = arg count val.a = builtintable entry */
2950 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2951 /* op1 = arg count, val.a = method pointer */
2953 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2954 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2955 case ICMD_INVOKEINTERFACE:
2960 unresolved_method *um = iptr->target;
2961 md = um->methodref->parseddesc.md;
2963 md = lm->parseddesc;
2967 s3 = md->paramcount;
2969 MCODECHECK((s3 << 1) + 64);
2971 /* copy arguments to registers or stack location */
2973 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2974 if (src->varkind == ARGVAR)
2976 if (IS_INT_LNG_TYPE(src->type)) {
2977 if (!md->params[s3].inmemory) {
2978 s1 = rd->argintregs[md->params[s3].regoff];
2979 var_to_reg_int(d, src, s1);
2982 var_to_reg_int(d, src, REG_ITMP1);
2983 M_LST(d, REG_SP, md->params[s3].regoff * 8);
2987 if (!md->params[s3].inmemory) {
2988 s1 = rd->argfltregs[md->params[s3].regoff];
2989 var_to_reg_flt(d, src, s1);
2990 M_TFLTMOVE(src->type, d, s1);
2992 var_to_reg_flt(d, src, REG_FTMP1);
2993 M_DST(d, REG_SP, md->params[s3].regoff * 8);
2998 switch (iptr->opc) {
3000 disp = dseg_addaddress(cd, bte->fp);
3001 d = md->returntype.type;
3003 M_ALD(REG_ITMP3, REG_PV, disp); /* built-in-function pointer */
3004 M_JSR(REG_RA, REG_ITMP3);
3006 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3007 M_LDA(REG_PV, REG_RA, -disp);
3009 /* if op1 == true, we need to check for an exception */
3011 if (iptr->op1 == true) {
3012 M_BEQZ(REG_RESULT, 0);
3013 codegen_addxexceptionrefs(cd, mcodeptr);
3018 case ICMD_INVOKESPECIAL:
3019 M_BEQZ(rd->argintregs[0], 0);
3020 codegen_addxnullrefs(cd, mcodeptr);
3024 case ICMD_INVOKESTATIC:
3026 unresolved_method *um = iptr->target;
3028 disp = dseg_addaddress(cd, NULL);
3030 codegen_addpatchref(cd, mcodeptr,
3031 PATCHER_invokestatic_special, um, disp);
3033 if (opt_showdisassemble) {
3037 d = um->methodref->parseddesc.md->returntype.type;
3040 disp = dseg_addaddress(cd, lm->stubroutine);
3041 d = lm->parseddesc->returntype.type;
3044 M_ALD(REG_PV, REG_PV, disp); /* method pointer in pv */
3045 M_JSR(REG_RA, REG_PV);
3047 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3048 M_LDA(REG_PV, REG_RA, -disp);
3051 case ICMD_INVOKEVIRTUAL:
3052 gen_nullptr_check(rd->argintregs[0]);
3055 unresolved_method *um = iptr->target;
3057 codegen_addpatchref(cd, mcodeptr,
3058 PATCHER_invokevirtual, um, 0);
3060 if (opt_showdisassemble) {
3065 d = um->methodref->parseddesc.md->returntype.type;
3068 s1 = OFFSET(vftbl_t, table[0]) +
3069 sizeof(methodptr) * lm->vftblindex;
3070 d = lm->parseddesc->returntype.type;
3073 M_ALD(REG_METHODPTR, rd->argintregs[0],
3074 OFFSET(java_objectheader, vftbl));
3075 M_ALD(REG_PV, REG_METHODPTR, s1);
3076 M_JSR(REG_RA, REG_PV);
3078 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3079 M_LDA(REG_PV, REG_RA, -disp);
3082 case ICMD_INVOKEINTERFACE:
3083 gen_nullptr_check(rd->argintregs[0]);
3086 unresolved_method *um = iptr->target;
3088 codegen_addpatchref(cd, mcodeptr,
3089 PATCHER_invokeinterface, um, 0);
3091 if (opt_showdisassemble) {
3097 d = um->methodref->parseddesc.md->returntype.type;
3100 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3101 sizeof(methodptr*) * lm->class->index;
3103 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3105 d = lm->parseddesc->returntype.type;
3108 M_ALD(REG_METHODPTR, rd->argintregs[0],
3109 OFFSET(java_objectheader, vftbl));
3110 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3111 M_ALD(REG_PV, REG_METHODPTR, s2);
3112 M_JSR(REG_RA, REG_PV);
3114 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3115 M_LDA(REG_PV, REG_RA, -disp);
3119 /* d contains return type */
3121 if (d != TYPE_VOID) {
3122 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3123 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3124 M_INTMOVE(REG_RESULT, s1);
3125 store_reg_to_var_int(iptr->dst, s1);
3127 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3128 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3129 store_reg_to_var_flt(iptr->dst, s1);
3135 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3136 /* op1: 0 == array, 1 == class */
3137 /* val.a: (classinfo*) superclass */
3139 /* superclass is an interface:
3141 * OK if ((sub == NULL) ||
3142 * (sub->vftbl->interfacetablelength > super->index) &&
3143 * (sub->vftbl->interfacetable[-super->index] != NULL));
3145 * superclass is a class:
3147 * OK if ((sub == NULL) || (0
3148 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3149 * super->vftbl->diffvall));
3152 if (iptr->op1 == 1) {
3154 vftbl_t *supervftbl;
3157 super = (classinfo *) iptr->val.a;
3164 superindex = super->index;
3165 supervftbl = super->vftbl;
3168 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3169 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3172 var_to_reg_int(s1, src, REG_ITMP1);
3174 /* calculate interface checkcast code size */
3178 s2 += (opt_showdisassemble ? 2 : 0);
3180 /* calculate class checkcast code size */
3182 s3 = 10 /* 10 + (s1 == REG_ITMP1) */;
3184 s3 += (opt_showdisassemble ? 2 : 0);
3186 /* if class is not resolved, check which code to call */
3189 M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
3192 disp = dseg_adds4(cd, 0); /* super->flags */
3194 codegen_addpatchref(cd, mcodeptr,
3195 PATCHER_checkcast_instanceof_flags,
3196 (constant_classref *) iptr->target,
3199 if (opt_showdisassemble) {
3203 /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
3204 M_ILD(REG_ITMP2, REG_PV, disp);
3205 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3206 M_BEQZ(REG_ITMP2, 1 + s2 + 2);
3210 /* interface checkcast code */
3212 if (!super || super->flags & ACC_INTERFACE) {
3218 codegen_addpatchref(cd, mcodeptr,
3219 PATCHER_checkcast_instanceof_interface,
3220 (constant_classref *) iptr->target,
3223 if (opt_showdisassemble) {
3228 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3229 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3230 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3231 M_BLEZ(REG_ITMP3, 0);
3232 codegen_addxcastrefs(cd, mcodeptr);
3234 M_ALD(REG_ITMP3, REG_ITMP2,
3235 OFFSET(vftbl_t, interfacetable[0]) -
3236 superindex * sizeof(methodptr*));
3237 M_BEQZ(REG_ITMP3, 0);
3238 codegen_addxcastrefs(cd, mcodeptr);
3247 /* class checkcast code */
3249 if (!super || !(super->flags & ACC_INTERFACE)) {
3250 disp = dseg_addaddress(cd, (void *) supervftbl);
3257 codegen_addpatchref(cd, mcodeptr,
3258 PATCHER_checkcast_instanceof_class,
3259 (constant_classref *) iptr->target,
3262 if (opt_showdisassemble) {
3267 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3268 M_ALD(REG_ITMP3, REG_PV, disp);
3269 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3270 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3272 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3273 /* if (s1 != REG_ITMP1) { */
3274 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
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); */
3279 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3281 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3282 M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3283 M_ALD(REG_ITMP3, REG_PV, disp);
3284 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3285 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3286 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3289 M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3290 M_BNEZ(REG_ITMP3, 0);
3291 codegen_addxcastrefs(cd, mcodeptr);
3294 d = reg_of_var(rd, iptr->dst, s1);
3297 var_to_reg_int(s1, src, rd->argintregs[0]);
3298 M_INTMOVE(s1, rd->argintregs[0]);
3300 disp = dseg_addaddress(cd, iptr->val.a);
3302 if (iptr->val.a == NULL) {
3303 codegen_addpatchref(cd, mcodeptr,
3304 PATCHER_builtin_arraycheckcast,
3305 (constant_classref *) iptr->target,
3308 if (opt_showdisassemble) {
3313 M_ALD(rd->argintregs[1], REG_PV, disp);
3314 disp = dseg_addaddress(cd, BUILTIN_arraycheckcast);
3315 M_ALD(REG_ITMP3, REG_PV, disp);
3316 M_JSR(REG_RA, REG_ITMP3);
3319 M_BEQZ(REG_RESULT, 0);
3320 codegen_addxcastrefs(cd, mcodeptr);
3323 var_to_reg_int(s1, src, REG_ITMP1);
3324 d = reg_of_var(rd, iptr->dst, s1);
3327 store_reg_to_var_int(iptr->dst, d);
3330 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3331 /* op1: 0 == array, 1 == class */
3332 /* val.a: (classinfo*) superclass */
3334 /* superclass is an interface:
3336 * return (sub != NULL) &&
3337 * (sub->vftbl->interfacetablelength > super->index) &&
3338 * (sub->vftbl->interfacetable[-super->index] != NULL);
3340 * superclass is a class:
3342 * return ((sub != NULL) && (0
3343 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3344 * super->vftbl->diffvall));
3349 vftbl_t *supervftbl;
3352 super = (classinfo *) iptr->val.a;
3359 superindex = super->index;
3360 supervftbl = super->vftbl;
3363 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3364 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3367 var_to_reg_int(s1, src, REG_ITMP1);
3368 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3370 M_MOV(s1, REG_ITMP1);
3374 /* calculate interface instanceof code size */
3378 s2 += (opt_showdisassemble ? 2 : 0);
3380 /* calculate class instanceof code size */
3384 s3 += (opt_showdisassemble ? 2 : 0);
3388 /* if class is not resolved, check which code to call */
3391 M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
3394 disp = dseg_adds4(cd, 0); /* super->flags */
3396 codegen_addpatchref(cd, mcodeptr,
3397 PATCHER_checkcast_instanceof_flags,
3398 (constant_classref *) iptr->target, disp);
3400 if (opt_showdisassemble) {
3404 /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
3405 M_ILD(REG_ITMP3, REG_PV, disp);
3406 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
3407 M_BEQZ(REG_ITMP3, 1 + s2 + 2);
3411 /* interface instanceof code */
3413 if (!super || (super->flags & ACC_INTERFACE)) {
3419 codegen_addpatchref(cd, mcodeptr,
3420 PATCHER_checkcast_instanceof_interface,
3421 (constant_classref *) iptr->target, 0);
3423 if (opt_showdisassemble) {
3428 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3429 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3430 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3431 M_BLEZ(REG_ITMP3, 3);
3433 M_ALD(REG_ITMP1, REG_ITMP1,
3434 OFFSET(vftbl_t, interfacetable[0]) -
3435 superindex * sizeof(methodptr*));
3436 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3444 /* class instanceof code */
3446 if (!super || !(super->flags & ACC_INTERFACE)) {
3447 disp = dseg_addaddress(cd, supervftbl);
3454 codegen_addpatchref(cd, mcodeptr,
3455 PATCHER_checkcast_instanceof_class,
3456 (constant_classref *) iptr->target,
3459 if (opt_showdisassemble) {
3464 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3465 M_ALD(REG_ITMP2, REG_PV, disp);
3466 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3467 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3469 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3470 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3471 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3472 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3473 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3475 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3476 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3479 store_reg_to_var_int(iptr->dst, d);
3483 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3484 /* op1 = dimension, val.a = class */
3486 /* check for negative sizes and copy sizes to stack if necessary */
3488 MCODECHECK((iptr->op1 << 1) + 64);
3490 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3491 /* copy SAVEDVAR sizes to stack */
3493 if (src->varkind != ARGVAR) {
3494 var_to_reg_int(s2, src, REG_ITMP1);
3495 M_LST(s2, REG_SP, s1 * 8);
3499 /* a0 = dimension count */
3501 ICONST(rd->argintregs[0], iptr->op1);
3503 /* is patcher function set? */
3505 if (iptr->val.a == NULL) {
3506 disp = dseg_addaddress(cd, NULL);
3508 codegen_addpatchref(cd, mcodeptr,
3509 PATCHER_builtin_multianewarray,
3510 (constant_classref *) iptr->target,
3513 if (opt_showdisassemble) {
3518 disp = dseg_addaddress(cd, iptr->val.a);
3521 /* a1 = arraydescriptor */
3523 M_ALD(rd->argintregs[1], REG_PV, disp);
3525 /* a2 = pointer to dimensions = stack pointer */
3527 M_INTMOVE(REG_SP, rd->argintregs[2]);
3529 disp = dseg_addaddress(cd, BUILTIN_multianewarray);
3530 M_ALD(REG_ITMP3, REG_PV, disp);
3531 M_JSR(REG_RA, REG_ITMP3);
3534 /* check for exception before result assignment */
3536 M_BEQZ(REG_RESULT, 0);
3537 codegen_addxexceptionrefs(cd, mcodeptr);
3540 d = reg_of_var(rd, iptr->dst, REG_RESULT);
3541 M_INTMOVE(REG_RESULT, d);
3542 store_reg_to_var_int(iptr->dst, d);
3546 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3550 } /* for instruction */
3552 /* copy values to interface registers */
3554 src = bptr->outstack;
3555 len = bptr->outdepth;
3557 #if defined(ENABLE_LSRA)
3562 if ((src->varkind != STACKVAR)) {
3564 if (IS_FLT_DBL_TYPE(s2)) {
3565 var_to_reg_flt(s1, src, REG_FTMP1);
3566 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3567 M_TFLTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3570 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3574 var_to_reg_int(s1, src, REG_ITMP1);
3575 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3576 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3579 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3586 /* At the end of a basic block we may have to append some nops,
3587 because the patcher stub calling code might be longer than the
3588 actual instruction. So codepatching does not change the
3589 following block unintentionally. */
3591 if ((u1 *) mcodeptr < cd->lastmcodeptr) {
3592 while ((u1 *) mcodeptr < cd->lastmcodeptr) {
3597 } /* if (bptr -> flags >= BBREACHED) */
3598 } /* for basic block */
3600 dseg_createlinenumbertable(cd);
3606 /* generate ArithmeticException stubs */
3610 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3611 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3613 (u1 *) mcodeptr - cd->mcodebase);
3617 if (xcodeptr != NULL) {
3618 M_BR(xcodeptr - mcodeptr);
3619 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3622 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3624 xcodeptr = mcodeptr;
3626 M_MOV(REG_PV, rd->argintregs[0]);
3627 M_MOV(REG_SP, rd->argintregs[1]);
3629 if (m->isleafmethod)
3630 M_MOV(REG_RA, rd->argintregs[2]);
3632 M_ALD(rd->argintregs[2],
3633 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3635 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3637 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3638 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3640 if (m->isleafmethod)
3641 M_AST(REG_RA, REG_SP, 1 * 8);
3643 a = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
3644 M_ALD(REG_ITMP3, REG_PV, a);
3645 M_JSR(REG_RA, REG_ITMP3);
3647 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3649 if (m->isleafmethod)
3650 M_ALD(REG_RA, REG_SP, 1 * 8);
3652 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3653 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3655 a = dseg_addaddress(cd, asm_handle_exception);
3656 M_ALD(REG_ITMP3, REG_PV, a);
3662 /* generate ArrayIndexOutOfBoundsException stubs */
3666 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3667 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3669 (u1 *) mcodeptr - cd->mcodebase);
3673 /* move index register into REG_ITMP1 */
3675 M_MOV(bref->reg, REG_ITMP1);
3676 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3678 if (xcodeptr != NULL) {
3679 M_BR(xcodeptr - mcodeptr);
3683 xcodeptr = mcodeptr;
3685 M_MOV(REG_PV, rd->argintregs[0]);
3686 M_MOV(REG_SP, rd->argintregs[1]);
3688 if (m->isleafmethod)
3689 M_MOV(REG_RA, rd->argintregs[2]);
3691 M_ALD(rd->argintregs[2],
3692 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3694 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3695 M_MOV(REG_ITMP1, rd->argintregs[4]);
3697 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3698 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3700 if (m->isleafmethod)
3701 M_AST(REG_RA, REG_SP, 1 * 8);
3703 a = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
3704 M_ALD(REG_ITMP3, REG_PV, a);
3705 M_JSR(REG_RA, REG_ITMP3);
3707 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3709 if (m->isleafmethod)
3710 M_ALD(REG_RA, REG_SP, 1 * 8);
3712 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3713 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3715 a = dseg_addaddress(cd, asm_handle_exception);
3716 M_ALD(REG_ITMP3, REG_PV, a);
3722 /* generate ArrayStoreException stubs */
3726 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
3727 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3729 (u1 *) mcodeptr - cd->mcodebase);
3733 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3735 if (xcodeptr != NULL) {
3736 M_BR(xcodeptr - mcodeptr);
3740 xcodeptr = mcodeptr;
3742 M_MOV(REG_PV, rd->argintregs[0]);
3743 M_MOV(REG_SP, rd->argintregs[1]);
3744 M_ALD(rd->argintregs[2],
3745 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3746 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3748 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3749 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3751 a = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
3752 M_ALD(REG_ITMP3, REG_PV, a);
3753 M_JSR(REG_RA, REG_ITMP3);
3755 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3757 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3758 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3760 a = dseg_addaddress(cd, asm_handle_exception);
3761 M_ALD(REG_ITMP3, REG_PV, a);
3767 /* generate ClassCastException stubs */
3771 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3772 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3774 (u1 *) mcodeptr - cd->mcodebase);
3778 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3780 if (xcodeptr != NULL) {
3781 M_BR(xcodeptr - mcodeptr);
3785 xcodeptr = mcodeptr;
3787 M_MOV(REG_PV, rd->argintregs[0]);
3788 M_MOV(REG_SP, rd->argintregs[1]);
3790 if (m->isleafmethod)
3791 M_MOV(REG_RA, rd->argintregs[2]);
3793 M_ALD(rd->argintregs[2],
3794 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3796 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3798 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3799 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3801 if (m->isleafmethod)
3802 M_AST(REG_RA, REG_SP, 1 * 8);
3804 a = dseg_addaddress(cd, stacktrace_inline_classcastexception);
3805 M_ALD(REG_ITMP3, REG_PV, a);
3806 M_JSR(REG_RA, REG_ITMP3);
3808 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3810 if (m->isleafmethod)
3811 M_ALD(REG_RA, REG_SP, 1 * 8);
3813 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3814 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3816 a = dseg_addaddress(cd, asm_handle_exception);
3817 M_ALD(REG_ITMP3, REG_PV, a);
3823 /* generate NullPointerException stubs */
3827 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3828 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3830 (u1 *) mcodeptr - cd->mcodebase);
3834 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3836 if (xcodeptr != NULL) {
3837 M_BR(xcodeptr - mcodeptr);
3841 xcodeptr = mcodeptr;
3843 M_MOV(REG_PV, rd->argintregs[0]);
3844 M_MOV(REG_SP, rd->argintregs[1]);
3846 if (m->isleafmethod)
3847 M_MOV(REG_RA, rd->argintregs[2]);
3849 M_ALD(rd->argintregs[2],
3850 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3852 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3854 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3855 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3857 if (m->isleafmethod)
3858 M_AST(REG_RA, REG_SP, 1 * 8);
3860 a = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
3861 M_ALD(REG_ITMP3, REG_PV, a);
3862 M_JSR(REG_RA, REG_ITMP3);
3864 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3866 if (m->isleafmethod)
3867 M_ALD(REG_RA, REG_SP, 1 * 8);
3869 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3870 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3872 a = dseg_addaddress(cd, asm_handle_exception);
3873 M_ALD(REG_ITMP3, REG_PV, a);
3879 /* generate exception check stubs */
3883 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3884 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3886 (u1 *) mcodeptr - cd->mcodebase);
3890 if (xcodeptr != NULL) {
3891 M_BR(xcodeptr - mcodeptr);
3892 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3895 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3897 xcodeptr = mcodeptr;
3899 M_MOV(REG_PV, rd->argintregs[0]);
3900 M_MOV(REG_SP, rd->argintregs[1]);
3901 M_ALD(rd->argintregs[2],
3902 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3903 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3905 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3906 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3908 a = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
3909 M_ALD(REG_ITMP3, REG_PV, a);
3910 M_JSR(REG_RA, REG_ITMP3);
3912 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3914 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3915 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3917 a = dseg_addaddress(cd, asm_handle_exception);
3918 M_ALD(REG_ITMP3, REG_PV, a);
3924 /* generate patcher stub call code */
3931 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3932 /* check code segment size */
3936 /* Get machine code which is patched back in later. The call is */
3937 /* 2 instruction words long. */
3939 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3941 /* We need to split this, because an unaligned 8 byte read causes */
3944 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3946 /* patch in the call to call the following code (done at compile */
3949 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3950 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3952 disp = (s4) (tmpmcodeptr - (xcodeptr + 1));
3954 if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) {
3956 new_internalerror("Jump offset is out of range: %d > +/-%d",
3964 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3966 /* create stack frame */
3968 M_ASUB_IMM(REG_SP, 6 * 8, REG_SP);
3970 /* calculate return address and move it onto the stack */
3972 M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
3973 M_AST(REG_ITMP3, REG_SP, 5 * 8);
3975 /* move pointer to java_objectheader onto stack */
3977 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3978 /* create a virtual java_objectheader */
3980 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3981 disp = dseg_addaddress(cd, NULL); /* vftbl */
3983 M_LDA(REG_ITMP3, REG_PV, disp);
3984 M_AST(REG_ITMP3, REG_SP, 4 * 8);
3989 /* move machine code onto stack */
3991 disp = dseg_adds8(cd, mcode);
3992 M_LLD(REG_ITMP3, REG_PV, disp);
3993 M_LST(REG_ITMP3, REG_SP, 3 * 8);
3995 /* move class/method/field reference onto stack */
3997 disp = dseg_addaddress(cd, pref->ref);
3998 M_ALD(REG_ITMP3, REG_PV, disp);
3999 M_AST(REG_ITMP3, REG_SP, 2 * 8);
4001 /* move data segment displacement onto stack */
4003 disp = dseg_adds4(cd, pref->disp);
4004 M_ILD(REG_ITMP3, REG_PV, disp);
4005 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4007 /* move patcher function pointer onto stack */
4009 disp = dseg_addaddress(cd, pref->patcher);
4010 M_ALD(REG_ITMP3, REG_PV, disp);
4011 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4013 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4014 M_ALD(REG_ITMP3, REG_PV, disp);
4021 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4023 docacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4025 /* everything's ok */
4031 /* createcompilerstub **********************************************************
4033 Creates a stub routine which calls the compiler.
4035 *******************************************************************************/
4037 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
4038 #define COMPILERSTUB_CODESIZE 4 * 4
4040 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4043 u1 *createcompilerstub(methodinfo *m)
4045 ptrint *s; /* memory to hold the stub */
4046 s4 *mcodeptr; /* code generation pointer */
4048 s = (ptrint *) CNEW(u1, COMPILERSTUB_SIZE);
4051 s[1] = (ptrint) asm_call_jit_compiler;
4053 mcodeptr = (s4 *) (s + 2);
4055 M_ALD(REG_ITMP1, REG_PV, -2 * SIZEOF_VOID_P); /* method pointer */
4056 M_ALD(REG_PV, REG_PV, -1 * SIZEOF_VOID_P); /* pointer to compiler */
4060 (void) docacheflush((void *) s, (char *) mcodeptr - (char *) s);
4062 #if defined(ENABLE_STATISTICS)
4064 count_cstub_len += COMPILERSTUB_SIZE;
4067 return (((u1 *) s) + COMPILERSTUB_DATASIZE);
4071 /* createnativestub ************************************************************
4073 Creates a stub routine which calls a native method.
4075 *******************************************************************************/
4077 u1 *createnativestub(functionptr f, methodinfo *m, codegendata *cd,
4078 registerdata *rd, methoddesc *nmd)
4080 s4 *mcodeptr; /* code generation pointer */
4081 s4 stackframesize; /* size of stackframe if needed */
4084 s4 i, j; /* count variables */
4087 s4 funcdisp; /* displacement of the function */
4090 /* initialize variables */
4093 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4096 /* calculate stack frame size */
4099 1 + /* return address */
4100 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4101 sizeof(localref_table) / SIZEOF_VOID_P +
4102 md->paramcount + /* for saving arguments over calls */
4103 1 + /* for saving return address */
4107 /* create method header */
4109 #if SIZEOF_VOID_P == 4
4110 (void) dseg_addaddress(cd, m); /* MethodPointer */
4112 (void) dseg_addaddress(cd, m); /* MethodPointer */
4113 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4114 (void) dseg_adds4(cd, 0); /* IsSync */
4115 (void) dseg_adds4(cd, 0); /* IsLeaf */
4116 (void) dseg_adds4(cd, 0); /* IntSave */
4117 (void) dseg_adds4(cd, 0); /* FltSave */
4118 (void) dseg_addlinenumbertablesize(cd);
4119 (void) dseg_adds4(cd, 0); /* ExTableSize */
4122 /* initialize mcode variables */
4124 mcodeptr = (s4 *) cd->mcodeptr;
4127 /* generate stub code */
4129 M_LDA(REG_SP, REG_SP, -stackframesize * 8); /* build up stackframe */
4130 M_AST(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* store ra */
4133 /* call trace function */
4136 M_LDA(REG_SP, REG_SP, -(1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4138 /* save integer argument registers */
4140 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4141 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4142 M_LST(rd->argintregs[i], REG_SP, (1 + i) * 8);
4144 /* save and copy float arguments into integer registers */
4146 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4147 t = md->paramtypes[i].type;
4149 if (IS_FLT_DBL_TYPE(t)) {
4150 if (IS_2_WORD_TYPE(t)) {
4151 M_DST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4152 M_LLD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4154 M_FST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4155 M_ILD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4160 disp = dseg_addaddress(cd, m);
4161 M_ALD(REG_ITMP1, REG_PV, disp);
4162 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4163 disp = dseg_addaddress(cd, builtin_trace_args);
4164 M_ALD(REG_ITMP3, REG_PV, disp);
4165 M_JSR(REG_RA, REG_ITMP3);
4168 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4169 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4170 M_LLD(rd->argintregs[i], REG_SP, (1 + i) * 8);
4172 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4173 t = md->paramtypes[i].type;
4175 if (IS_FLT_DBL_TYPE(t)) {
4176 if (IS_2_WORD_TYPE(t)) {
4177 M_DLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4179 M_FLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4184 M_LDA(REG_SP, REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4188 /* get function address (this must happen before the stackframeinfo) */
4190 funcdisp = dseg_addaddress(cd, f);
4192 #if !defined(ENABLE_STATICVM)
4194 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m, funcdisp);
4196 if (opt_showdisassemble) {
4202 /* save integer and float argument registers */
4204 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4205 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4206 M_LST(rd->argintregs[i], REG_SP, j * 8);
4211 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4212 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4213 M_DST(rd->argfltregs[i], REG_SP, j * 8);
4218 /* prepare data structures for native function call */
4220 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4221 M_MOV(REG_PV, rd->argintregs[1]);
4222 M_AADD_IMM(REG_SP, stackframesize * 8, rd->argintregs[2]);
4223 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8 - SIZEOF_VOID_P);
4224 disp = dseg_addaddress(cd, codegen_start_native_call);
4225 M_ALD(REG_ITMP3, REG_PV, disp);
4226 M_JSR(REG_RA, REG_ITMP3);
4227 M_NOP; /* XXX fill me! */
4229 /* restore integer and float argument registers */
4231 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4232 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4233 M_LLD(rd->argintregs[i], REG_SP, j * 8);
4238 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4239 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4240 M_DLD(rd->argfltregs[i], REG_SP, j * 8);
4245 /* copy or spill arguments to new locations */
4247 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4248 t = md->paramtypes[i].type;
4250 if (IS_INT_LNG_TYPE(t)) {
4251 if (!md->params[i].inmemory) {
4252 s1 = rd->argintregs[md->params[i].regoff];
4254 if (!nmd->params[j].inmemory) {
4255 s2 = rd->argintregs[nmd->params[j].regoff];
4258 s2 = nmd->params[j].regoff;
4259 M_AST(s1, REG_SP, s2 * 8);
4263 s1 = md->params[i].regoff + stackframesize;
4264 s2 = nmd->params[j].regoff;
4265 M_ALD(REG_ITMP1, REG_SP, s1 * 8);
4266 M_AST(REG_ITMP1, REG_SP, s2 * 8);
4270 if (!md->params[i].inmemory) {
4271 s1 = rd->argfltregs[md->params[i].regoff];
4273 if (!nmd->params[j].inmemory) {
4274 s2 = rd->argfltregs[nmd->params[j].regoff];
4275 M_TFLTMOVE(t, s1, s2);
4277 s2 = nmd->params[j].regoff;
4278 if (IS_2_WORD_TYPE(t))
4279 M_DST(s1, REG_SP, s2 * 8);
4281 M_FST(s1, REG_SP, s2 * 8);
4285 s1 = md->params[i].regoff + stackframesize;
4286 s2 = nmd->params[j].regoff;
4287 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4288 if (IS_2_WORD_TYPE(t))
4289 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4291 M_FST(REG_FTMP1, REG_SP, s2 * 8);
4296 /* put class into second argument register */
4298 if (m->flags & ACC_STATIC) {
4299 disp = dseg_addaddress(cd, m->class);
4300 M_ALD(rd->argintregs[1], REG_PV, disp);
4303 /* put env into first argument register */
4305 disp = dseg_addaddress(cd, &env);
4306 M_ALD(rd->argintregs[0], REG_PV, disp);
4308 /* do the native function call */
4310 M_ALD(REG_ITMP3, REG_PV, funcdisp); /* load adress of native method */
4311 M_JSR(REG_RA, REG_ITMP3); /* call native method */
4312 M_NOP; /* delay slot */
4314 /* save return value */
4316 if (IS_INT_LNG_TYPE(md->returntype.type))
4317 M_LST(REG_RESULT, REG_SP, 0 * 8);
4319 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4321 /* remove native stackframe info */
4323 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4324 disp = dseg_addaddress(cd, codegen_finish_native_call);
4325 M_ALD(REG_ITMP3, REG_PV, disp);
4326 M_JSR(REG_RA, REG_ITMP3);
4327 M_NOP; /* XXX fill me! */
4329 /* call finished trace function */
4332 if (IS_INT_LNG_TYPE(md->returntype.type))
4333 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4335 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4337 disp = dseg_addaddress(cd, m);
4338 M_ALD(rd->argintregs[0], REG_PV, disp);
4340 M_MOV(REG_RESULT, rd->argintregs[1]);
4341 M_DMFC1(REG_ITMP1, REG_FRESULT);
4342 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4343 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4345 disp = dseg_addaddress(cd, builtin_displaymethodstop);
4346 M_ALD(REG_ITMP3, REG_PV, disp);
4347 M_JSR(REG_RA, REG_ITMP3);
4351 /* check for exception */
4353 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4354 disp = dseg_addaddress(cd, builtin_get_exceptionptrptr);
4355 M_ALD(REG_ITMP3, REG_PV, disp);
4356 M_JSR(REG_RA, REG_ITMP3);
4358 M_MOV(REG_RESULT, REG_ITMP3);
4360 disp = dseg_addaddress(cd, &_exceptionptr);
4361 M_ALD(REG_ITMP3, REG_PV, disp); /* get address of exceptionptr */
4363 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4365 M_ALD(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* load ra */
4367 /* restore return value */
4369 if (IS_INT_LNG_TYPE(md->returntype.type))
4370 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4372 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4374 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
4375 M_LDA(REG_SP, REG_SP, stackframesize * 8);/* remove stackframe, DELAY SLOT*/
4377 M_RET(REG_RA); /* return to caller */
4378 M_NOP; /* DELAY SLOT */
4380 /* handle exception */
4382 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4384 disp = dseg_addaddress(cd, asm_handle_nat_exception);
4385 M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */
4386 M_JMP(REG_ITMP3); /* jump to asm exception handler */
4387 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4390 /* generate static stub call code */
4398 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4399 /* Get machine code which is patched back in later. The call is */
4400 /* 2 instruction words long. */
4402 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4404 /* We need to split this, because an unaligned 8 byte read causes */
4407 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
4409 /* patch in the call to call the following code (done at compile */
4412 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4413 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4415 M_BRS(tmpmcodeptr - (xcodeptr + 1));
4416 M_NOP; /* branch delay slot */
4418 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4420 /* create stack frame */
4422 M_LSUB_IMM(REG_SP, 6 * 8, REG_SP);
4424 /* move return address onto stack */
4426 M_AST(REG_RA, REG_SP, 5 * 8);
4428 /* move pointer to java_objectheader onto stack */
4430 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4431 /* order reversed because of data segment layout */
4433 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4434 disp = dseg_addaddress(cd, NULL); /* vftbl */
4436 M_LDA(REG_ITMP3, REG_PV, disp);
4437 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4439 M_AST(REG_ZERO, REG_SP, 4 * 8);
4442 /* move machine code onto stack */
4444 disp = dseg_adds8(cd, mcode);
4445 M_LLD(REG_ITMP3, REG_PV, disp);
4446 M_LST(REG_ITMP3, REG_SP, 3 * 8);
4448 /* move class/method/field reference onto stack */
4450 disp = dseg_addaddress(cd, pref->ref);
4451 M_ALD(REG_ITMP3, REG_PV, disp);
4452 M_AST(REG_ITMP3, REG_SP, 2 * 8);
4454 /* move data segment displacement onto stack */
4456 disp = dseg_adds4(cd, pref->disp);
4457 M_ILD(REG_ITMP3, REG_PV, disp);
4458 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4460 /* move patcher function pointer onto stack */
4462 disp = dseg_addaddress(cd, pref->patcher);
4463 M_ALD(REG_ITMP3, REG_PV, disp);
4464 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4466 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4467 M_ALD(REG_ITMP3, REG_PV, disp);
4473 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4475 docacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4477 return m->entrypoint;
4482 * These are local overrides for various environment variables in Emacs.
4483 * Please do not remove this and leave it at the end of the file, where
4484 * Emacs will automagically detect them.
4485 * ---------------------------------------------------------------------
4488 * indent-tabs-mode: t