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 4499 2006-02-13 00:12:24Z 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 /* initialize the last patcher pointer */
162 cd->lastmcodeptr = (u1 *) mcodeptr;
164 /* create stack frame (if necessary) */
167 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
169 /* save return address and used callee saved registers */
172 if (!m->isleafmethod) {
173 p--; M_AST(REG_RA, REG_SP, p * 8);
175 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
176 p--; M_AST(rd->savintregs[i], REG_SP, p * 8);
178 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
179 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
182 /* take arguments out of register or stack frame */
186 for (p = 0, l = 0; p < md->paramcount; p++) {
187 t = md->paramtypes[p].type;
188 var = &(rd->locals[l][t]);
190 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
194 s1 = md->params[p].regoff;
195 if (IS_INT_LNG_TYPE(t)) { /* integer args */
196 if (!md->params[p].inmemory) { /* register arguments */
197 s2 = rd->argintregs[s1];
198 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
199 M_INTMOVE(s2, var->regoff);
200 } else { /* reg arg -> spilled */
201 M_LST(s2, REG_SP, var->regoff * 8);
204 } else { /* stack arguments */
205 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
206 M_LLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
207 } else { /* stack arg -> spilled */
208 var->regoff = parentargs_base + s1;
212 } else { /* floating args */
213 if (!md->params[p].inmemory) { /* register arguments */
214 s2 = rd->argfltregs[s1];
215 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
216 M_TFLTMOVE(var->type, s2, var->regoff);
217 } else { /* reg arg -> spilled */
218 M_DST(s2, REG_SP, var->regoff * 8);
221 } else { /* stack arguments */
222 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
223 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
224 } else { /* stack-arg -> spilled */
225 var->regoff = parentargs_base + s1;
231 /* call monitorenter function */
233 #if defined(USE_THREADS)
234 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
235 /* stack offset for monitor argument */
240 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
242 for (p = 0; p < INT_ARG_CNT; p++)
243 M_LST(rd->argintregs[p], REG_SP, p * 8);
245 for (p = 0; p < FLT_ARG_CNT; p++)
246 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
248 s1 += INT_ARG_CNT + FLT_ARG_CNT;
251 /* decide which monitor enter function to call */
253 if (m->flags & ACC_STATIC) {
254 p = dseg_addaddress(cd, m->class);
255 M_ALD(rd->argintregs[0], REG_PV, p);
256 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
257 M_ALD(REG_ITMP3, REG_PV, p);
258 M_JSR(REG_RA, REG_ITMP3);
259 M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* branch delay */
262 M_BEQZ(rd->argintregs[0], 0);
263 codegen_addxnullrefs(cd, mcodeptr);
264 p = dseg_addaddress(cd, BUILTIN_monitorenter);
265 M_ALD(REG_ITMP3, REG_PV, p);
266 M_JSR(REG_RA, REG_ITMP3);
267 M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* branch delay */
271 for (p = 0; p < INT_ARG_CNT; p++)
272 M_LLD(rd->argintregs[p], REG_SP, p * 8);
274 for (p = 0; p < FLT_ARG_CNT; p++)
275 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
278 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
283 /* copy argument registers to stack and call trace function */
286 M_LDA(REG_SP, REG_SP, -(2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
287 M_AST(REG_RA, REG_SP, 1 * 8);
289 /* save integer argument registers */
291 for (p = 0; p < md->paramcount && p < INT_ARG_CNT; p++)
292 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
294 /* save and copy float arguments into integer registers */
296 for (p = 0; p < md->paramcount && p < FLT_ARG_CNT; p++) {
297 t = md->paramtypes[p].type;
299 if (IS_FLT_DBL_TYPE(t)) {
300 if (IS_2_WORD_TYPE(t)) {
301 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
302 M_LLD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
305 M_FST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
306 M_ILD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
310 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
314 /* save temporary registers for leaf methods */
316 if (m->isleafmethod) {
317 for (p = 0; p < INT_TMP_CNT; p++)
318 M_LST(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
320 for (p = 0; p < FLT_TMP_CNT; p++)
321 M_DST(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
324 p = dseg_addaddress(cd, m);
325 M_ALD(REG_ITMP1, REG_PV, p);
326 M_AST(REG_ITMP1, REG_SP, 0 * 8);
327 disp = dseg_addaddress(cd, (void *) builtin_trace_args);
328 M_ALD(REG_ITMP3, REG_PV, disp);
329 M_JSR(REG_RA, REG_ITMP3);
332 M_ALD(REG_RA, REG_SP, 1 * 8);
334 /* restore integer argument registers */
336 for (p = 0; p < md->paramcount && p < INT_ARG_CNT; p++)
337 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
339 /* restore float argument registers */
341 for (p = 0; p < md->paramcount && p < FLT_ARG_CNT; p++) {
342 t = md->paramtypes[p].type;
344 if (IS_FLT_DBL_TYPE(t)) {
345 if (IS_2_WORD_TYPE(t)) {
346 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
349 M_FLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
353 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
357 /* restore temporary registers for leaf methods */
359 if (m->isleafmethod) {
360 for (p = 0; p < INT_TMP_CNT; p++)
361 M_LLD(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
363 for (p = 0; p < FLT_TMP_CNT; p++)
364 M_DLD(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
367 M_LDA(REG_SP, REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
372 /* end of header generation */
374 /* walk through all basic blocks */
376 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
378 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
380 if (bptr->flags >= BBREACHED) {
382 /* branch resolving */
385 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
386 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
392 /* copy interface registers to their destination */
397 #if defined(ENABLE_LSRA)
399 while (src != NULL) {
401 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
402 /* d = reg_of_var(m, src, REG_ITMP1); */
403 if (!(src->flags & INMEMORY))
407 M_INTMOVE(REG_ITMP1, d);
408 store_reg_to_var_int(src, d);
414 while (src != NULL) {
416 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
417 d = reg_of_var(rd, src, REG_ITMP1);
418 M_INTMOVE(REG_ITMP1, d);
419 store_reg_to_var_int(src, d);
422 d = reg_of_var(rd, src, REG_IFTMP);
423 if ((src->varkind != STACKVAR)) {
425 if (IS_FLT_DBL_TYPE(s2)) {
426 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
427 s1 = rd->interfaces[len][s2].regoff;
428 M_TFLTMOVE(s2, s1, d);
431 M_DLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
433 store_reg_to_var_flt(src, d);
436 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
437 s1 = rd->interfaces[len][s2].regoff;
441 M_LLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
443 store_reg_to_var_int(src, d);
449 #if defined(ENABLE_LSRA)
452 /* walk through all instructions */
458 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
459 if (iptr->line != currentline) {
460 dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
461 currentline = iptr->line;
464 MCODECHECK(64); /* an instruction usually needs < 64 words */
468 case ICMD_NOP: /* ... ==> ... */
471 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
473 var_to_reg_int(s1, src, REG_ITMP1);
475 codegen_addxnullrefs(cd, mcodeptr);
479 /* constant operations ************************************************/
481 case ICMD_ICONST: /* ... ==> ..., constant */
482 /* op1 = 0, val.i = constant */
484 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
485 ICONST(d, iptr->val.i);
486 store_reg_to_var_int(iptr->dst, d);
489 case ICMD_LCONST: /* ... ==> ..., constant */
490 /* op1 = 0, val.l = constant */
492 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
493 LCONST(d, iptr->val.l);
494 store_reg_to_var_int(iptr->dst, d);
497 case ICMD_FCONST: /* ... ==> ..., constant */
498 /* op1 = 0, val.f = constant */
500 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
501 disp = dseg_addfloat(cd, iptr->val.f);
502 M_FLD(d, REG_PV, disp);
503 store_reg_to_var_flt(iptr->dst, d);
506 case ICMD_DCONST: /* ... ==> ..., constant */
507 /* op1 = 0, val.d = constant */
509 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
510 disp = dseg_adddouble(cd, iptr->val.d);
511 M_DLD(d, REG_PV, disp);
512 store_reg_to_var_flt (iptr->dst, d);
515 case ICMD_ACONST: /* ... ==> ..., constant */
516 /* op1 = 0, val.a = constant */
518 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
520 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
521 disp = dseg_addaddress(cd, iptr->val.a);
523 codegen_addpatchref(cd, mcodeptr,
525 (unresolved_class *) iptr->target, disp);
527 if (opt_showdisassemble) {
531 M_ALD(d, REG_PV, disp);
534 if (iptr->val.a == NULL) {
535 M_INTMOVE(REG_ZERO, d);
537 disp = dseg_addaddress(cd, iptr->val.a);
538 M_ALD(d, REG_PV, disp);
541 store_reg_to_var_int(iptr->dst, d);
545 /* load/store operations **********************************************/
547 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
548 case ICMD_LLOAD: /* op1 = local variable */
551 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
552 if ((iptr->dst->varkind == LOCALVAR) &&
553 (iptr->dst->varnum == iptr->op1))
555 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
556 if (var->flags & INMEMORY) {
557 M_LLD(d, REG_SP, 8 * var->regoff);
559 M_INTMOVE(var->regoff,d);
561 store_reg_to_var_int(iptr->dst, d);
564 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
565 case ICMD_DLOAD: /* op1 = local variable */
567 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
568 if ((iptr->dst->varkind == LOCALVAR) &&
569 (iptr->dst->varnum == iptr->op1))
571 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
573 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
574 if (var->flags & INMEMORY) {
575 M_CCFLD(var->type, t2, d, REG_SP, 8 * var->regoff);
577 M_CCFLTMOVE(var->type, t2, var->regoff, d);
580 store_reg_to_var_flt(iptr->dst, d);
584 case ICMD_ISTORE: /* ..., value ==> ... */
585 case ICMD_LSTORE: /* op1 = local variable */
588 if ((src->varkind == LOCALVAR) &&
589 (src->varnum == iptr->op1))
591 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
592 if (var->flags & INMEMORY) {
593 var_to_reg_int(s1, src, REG_ITMP1);
594 M_LST(s1, REG_SP, 8 * var->regoff);
597 var_to_reg_int(s1, src, var->regoff);
598 M_INTMOVE(s1, var->regoff);
602 case ICMD_FSTORE: /* ..., value ==> ... */
603 case ICMD_DSTORE: /* op1 = local variable */
605 if ((src->varkind == LOCALVAR) &&
606 (src->varnum == iptr->op1))
608 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
610 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
611 if (var->flags & INMEMORY) {
612 var_to_reg_flt(s1, src, REG_FTMP1);
613 M_CCFST(t1, var->type, s1, REG_SP, 8 * var->regoff);
616 var_to_reg_flt(s1, src, var->regoff);
617 M_CCFLTMOVE(t1, var->type, s1, var->regoff);
623 /* pop/dup/swap operations ********************************************/
625 /* attention: double and longs are only one entry in CACAO ICMDs */
627 case ICMD_POP: /* ..., value ==> ... */
628 case ICMD_POP2: /* ..., value, value ==> ... */
631 case ICMD_DUP: /* ..., a ==> ..., a, a */
632 M_COPY(src, iptr->dst);
635 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
637 M_COPY(src, iptr->dst);
638 M_COPY(src->prev, iptr->dst->prev);
639 M_COPY(iptr->dst, iptr->dst->prev->prev);
642 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
644 M_COPY(src, iptr->dst);
645 M_COPY(src->prev, iptr->dst->prev);
646 M_COPY(src->prev->prev, iptr->dst->prev->prev);
647 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
650 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
652 M_COPY(src, iptr->dst);
653 M_COPY(src->prev, iptr->dst->prev);
656 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
658 M_COPY(src, iptr->dst);
659 M_COPY(src->prev, iptr->dst->prev);
660 M_COPY(src->prev->prev, iptr->dst->prev->prev);
661 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
662 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
665 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
667 M_COPY(src, iptr->dst);
668 M_COPY(src->prev, iptr->dst->prev);
669 M_COPY(src->prev->prev, iptr->dst->prev->prev);
670 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
671 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
672 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
675 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
677 M_COPY(src, iptr->dst->prev);
678 M_COPY(src->prev, iptr->dst);
682 /* integer operations *************************************************/
684 case ICMD_INEG: /* ..., value ==> ..., - value */
686 var_to_reg_int(s1, src, REG_ITMP1);
687 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
688 M_ISUB(REG_ZERO, s1, d);
689 store_reg_to_var_int(iptr->dst, d);
692 case ICMD_LNEG: /* ..., value ==> ..., - value */
694 var_to_reg_int(s1, src, REG_ITMP1);
695 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
696 M_LSUB(REG_ZERO, s1, d);
697 store_reg_to_var_int(iptr->dst, d);
700 case ICMD_I2L: /* ..., value ==> ..., value */
702 var_to_reg_int(s1, src, REG_ITMP1);
703 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
705 store_reg_to_var_int(iptr->dst, d);
708 case ICMD_L2I: /* ..., value ==> ..., value */
710 var_to_reg_int(s1, src, REG_ITMP1);
711 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
712 M_ISLL_IMM(s1, 0, d );
713 store_reg_to_var_int(iptr->dst, d);
716 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
718 var_to_reg_int(s1, src, REG_ITMP1);
719 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
720 M_LSLL_IMM(s1, 56, d);
721 M_LSRA_IMM( d, 56, d);
722 store_reg_to_var_int(iptr->dst, d);
725 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
727 var_to_reg_int(s1, src, REG_ITMP1);
728 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
730 store_reg_to_var_int(iptr->dst, d);
733 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
735 var_to_reg_int(s1, src, REG_ITMP1);
736 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
737 M_LSLL_IMM(s1, 48, d);
738 M_LSRA_IMM( d, 48, d);
739 store_reg_to_var_int(iptr->dst, d);
743 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
745 var_to_reg_int(s1, src->prev, REG_ITMP1);
746 var_to_reg_int(s2, src, REG_ITMP2);
747 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
749 store_reg_to_var_int(iptr->dst, d);
752 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
753 /* val.i = constant */
755 var_to_reg_int(s1, src, REG_ITMP1);
756 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
757 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
758 M_IADD_IMM(s1, iptr->val.i, d);
760 ICONST(REG_ITMP2, iptr->val.i);
761 M_IADD(s1, REG_ITMP2, d);
763 store_reg_to_var_int(iptr->dst, d);
766 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
768 var_to_reg_int(s1, src->prev, REG_ITMP1);
769 var_to_reg_int(s2, src, REG_ITMP2);
770 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
772 store_reg_to_var_int(iptr->dst, d);
775 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
776 /* val.l = constant */
778 var_to_reg_int(s1, src, REG_ITMP1);
779 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
780 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
781 M_LADD_IMM(s1, iptr->val.l, d);
783 LCONST(REG_ITMP2, iptr->val.l);
784 M_LADD(s1, REG_ITMP2, d);
786 store_reg_to_var_int(iptr->dst, d);
789 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
791 var_to_reg_int(s1, src->prev, REG_ITMP1);
792 var_to_reg_int(s2, src, REG_ITMP2);
793 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
795 store_reg_to_var_int(iptr->dst, d);
798 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
799 /* val.i = constant */
801 var_to_reg_int(s1, src, REG_ITMP1);
802 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
803 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
804 M_IADD_IMM(s1, -iptr->val.i, d);
806 ICONST(REG_ITMP2, iptr->val.i);
807 M_ISUB(s1, REG_ITMP2, d);
809 store_reg_to_var_int(iptr->dst, d);
812 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
814 var_to_reg_int(s1, src->prev, REG_ITMP1);
815 var_to_reg_int(s2, src, REG_ITMP2);
816 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
818 store_reg_to_var_int(iptr->dst, d);
821 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
822 /* val.l = constant */
824 var_to_reg_int(s1, src, REG_ITMP1);
825 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
826 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
827 M_LADD_IMM(s1, -iptr->val.l, d);
829 LCONST(REG_ITMP2, iptr->val.l);
830 M_LSUB(s1, REG_ITMP2, d);
832 store_reg_to_var_int(iptr->dst, d);
835 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
837 var_to_reg_int(s1, src->prev, REG_ITMP1);
838 var_to_reg_int(s2, src, REG_ITMP2);
839 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
844 store_reg_to_var_int(iptr->dst, d);
847 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
848 /* val.i = constant */
850 var_to_reg_int(s1, src, REG_ITMP1);
851 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
852 ICONST(REG_ITMP2, iptr->val.i);
853 M_IMUL(s1, REG_ITMP2);
857 store_reg_to_var_int(iptr->dst, d);
860 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
862 var_to_reg_int(s1, src->prev, REG_ITMP1);
863 var_to_reg_int(s2, src, REG_ITMP2);
864 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
869 store_reg_to_var_int(iptr->dst, d);
872 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
873 /* val.l = constant */
875 var_to_reg_int(s1, src, REG_ITMP1);
876 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
877 LCONST(REG_ITMP2, iptr->val.l);
878 M_LMUL(s1, REG_ITMP2);
882 store_reg_to_var_int(iptr->dst, d);
885 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
887 var_to_reg_int(s1, src->prev, REG_ITMP1);
888 var_to_reg_int(s2, src, REG_ITMP2);
889 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
895 store_reg_to_var_int(iptr->dst, d);
898 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
900 var_to_reg_int(s1, src->prev, REG_ITMP1);
901 var_to_reg_int(s2, src, REG_ITMP2);
902 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
908 store_reg_to_var_int(iptr->dst, d);
911 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
913 var_to_reg_int(s1, src->prev, REG_ITMP1);
914 var_to_reg_int(s2, src, REG_ITMP2);
915 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
921 store_reg_to_var_int(iptr->dst, d);
924 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
926 var_to_reg_int(s1, src->prev, REG_ITMP1);
927 var_to_reg_int(s2, src, REG_ITMP2);
928 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
934 store_reg_to_var_int(iptr->dst, d);
937 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
938 case ICMD_LDIVPOW2: /* val.i = constant */
940 var_to_reg_int(s1, src, REG_ITMP1);
941 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
942 M_LSRA_IMM(s1, 63, REG_ITMP2);
943 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
944 M_LADD(s1, REG_ITMP2, REG_ITMP2);
945 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
946 store_reg_to_var_int(iptr->dst, d);
949 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
951 var_to_reg_int(s1, src->prev, REG_ITMP1);
952 var_to_reg_int(s2, src, REG_ITMP2);
953 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
955 store_reg_to_var_int(iptr->dst, d);
958 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
959 /* val.i = constant */
961 var_to_reg_int(s1, src, REG_ITMP1);
962 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
963 M_ISLL_IMM(s1, iptr->val.i, d);
964 store_reg_to_var_int(iptr->dst, d);
967 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
969 var_to_reg_int(s1, src->prev, REG_ITMP1);
970 var_to_reg_int(s2, src, REG_ITMP2);
971 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
973 store_reg_to_var_int(iptr->dst, d);
976 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
977 /* val.i = constant */
979 var_to_reg_int(s1, src, REG_ITMP1);
980 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
981 M_ISRA_IMM(s1, iptr->val.i, d);
982 store_reg_to_var_int(iptr->dst, d);
985 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
987 var_to_reg_int(s1, src->prev, REG_ITMP1);
988 var_to_reg_int(s2, src, REG_ITMP2);
989 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
991 store_reg_to_var_int(iptr->dst, d);
994 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
995 /* val.i = constant */
997 var_to_reg_int(s1, src, REG_ITMP1);
998 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
999 M_ISRL_IMM(s1, iptr->val.i, d);
1000 store_reg_to_var_int(iptr->dst, d);
1003 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1005 var_to_reg_int(s1, src->prev, REG_ITMP1);
1006 var_to_reg_int(s2, src, REG_ITMP2);
1007 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1009 store_reg_to_var_int(iptr->dst, d);
1012 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1013 /* val.i = constant */
1015 var_to_reg_int(s1, src, REG_ITMP1);
1016 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1017 M_LSLL_IMM(s1, iptr->val.i, d);
1018 store_reg_to_var_int(iptr->dst, d);
1021 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1023 var_to_reg_int(s1, src->prev, REG_ITMP1);
1024 var_to_reg_int(s2, src, REG_ITMP2);
1025 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1027 store_reg_to_var_int(iptr->dst, d);
1030 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1031 /* val.i = constant */
1033 var_to_reg_int(s1, src, REG_ITMP1);
1034 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1035 M_LSRA_IMM(s1, iptr->val.i, d);
1036 store_reg_to_var_int(iptr->dst, d);
1039 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1041 var_to_reg_int(s1, src->prev, REG_ITMP1);
1042 var_to_reg_int(s2, src, REG_ITMP2);
1043 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1045 store_reg_to_var_int(iptr->dst, d);
1048 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1049 /* val.i = constant */
1051 var_to_reg_int(s1, src, REG_ITMP1);
1052 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1053 M_LSRL_IMM(s1, iptr->val.i, d);
1054 store_reg_to_var_int(iptr->dst, d);
1057 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1060 var_to_reg_int(s1, src->prev, REG_ITMP1);
1061 var_to_reg_int(s2, src, REG_ITMP2);
1062 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1064 store_reg_to_var_int(iptr->dst, d);
1067 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1068 /* val.i = constant */
1070 var_to_reg_int(s1, src, REG_ITMP1);
1071 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1072 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1073 M_AND_IMM(s1, iptr->val.i, d);
1075 ICONST(REG_ITMP2, iptr->val.i);
1076 M_AND(s1, REG_ITMP2, d);
1078 store_reg_to_var_int(iptr->dst, d);
1081 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1082 /* val.i = constant */
1084 var_to_reg_int(s1, src, REG_ITMP1);
1085 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1087 M_MOV(s1, REG_ITMP1);
1090 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1091 M_AND_IMM(s1, iptr->val.i, d);
1094 M_ISUB(REG_ZERO, s1, d);
1095 M_AND_IMM(d, iptr->val.i, d);
1097 ICONST(REG_ITMP2, iptr->val.i);
1098 M_AND(s1, REG_ITMP2, d);
1101 M_ISUB(REG_ZERO, s1, d);
1102 M_AND(d, REG_ITMP2, d);
1104 M_ISUB(REG_ZERO, d, d);
1105 store_reg_to_var_int(iptr->dst, d);
1108 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1109 /* val.l = constant */
1111 var_to_reg_int(s1, src, REG_ITMP1);
1112 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1113 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1114 M_AND_IMM(s1, iptr->val.l, d);
1116 LCONST(REG_ITMP2, iptr->val.l);
1117 M_AND(s1, REG_ITMP2, d);
1119 store_reg_to_var_int(iptr->dst, d);
1122 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1123 /* val.l = constant */
1125 var_to_reg_int(s1, src, REG_ITMP1);
1126 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1128 M_MOV(s1, REG_ITMP1);
1131 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1132 M_AND_IMM(s1, iptr->val.l, d);
1135 M_LSUB(REG_ZERO, s1, d);
1136 M_AND_IMM(d, iptr->val.l, d);
1138 LCONST(REG_ITMP2, iptr->val.l);
1139 M_AND(s1, REG_ITMP2, d);
1142 M_LSUB(REG_ZERO, s1, d);
1143 M_AND(d, REG_ITMP2, d);
1145 M_LSUB(REG_ZERO, d, d);
1146 store_reg_to_var_int(iptr->dst, d);
1149 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1152 var_to_reg_int(s1, src->prev, REG_ITMP1);
1153 var_to_reg_int(s2, src, REG_ITMP2);
1154 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1156 store_reg_to_var_int(iptr->dst, d);
1159 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1160 /* val.i = constant */
1162 var_to_reg_int(s1, src, REG_ITMP1);
1163 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1164 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1165 M_OR_IMM(s1, iptr->val.i, d);
1167 ICONST(REG_ITMP2, iptr->val.i);
1168 M_OR(s1, REG_ITMP2, d);
1170 store_reg_to_var_int(iptr->dst, d);
1173 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1174 /* val.l = constant */
1176 var_to_reg_int(s1, src, REG_ITMP1);
1177 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1178 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1179 M_OR_IMM(s1, iptr->val.l, d);
1181 LCONST(REG_ITMP2, iptr->val.l);
1182 M_OR(s1, REG_ITMP2, d);
1184 store_reg_to_var_int(iptr->dst, d);
1187 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1190 var_to_reg_int(s1, src->prev, REG_ITMP1);
1191 var_to_reg_int(s2, src, REG_ITMP2);
1192 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1194 store_reg_to_var_int(iptr->dst, d);
1197 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1198 /* val.i = constant */
1200 var_to_reg_int(s1, src, REG_ITMP1);
1201 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1202 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1203 M_XOR_IMM(s1, iptr->val.i, d);
1205 ICONST(REG_ITMP2, iptr->val.i);
1206 M_XOR(s1, REG_ITMP2, d);
1208 store_reg_to_var_int(iptr->dst, d);
1211 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1212 /* val.l = constant */
1214 var_to_reg_int(s1, src, REG_ITMP1);
1215 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1216 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1217 M_XOR_IMM(s1, iptr->val.l, d);
1219 LCONST(REG_ITMP2, iptr->val.l);
1220 M_XOR(s1, REG_ITMP2, d);
1222 store_reg_to_var_int(iptr->dst, d);
1226 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1228 var_to_reg_int(s1, src->prev, REG_ITMP1);
1229 var_to_reg_int(s2, src, REG_ITMP2);
1230 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1231 M_CMPLT(s1, s2, REG_ITMP3);
1232 M_CMPLT(s2, s1, REG_ITMP1);
1233 M_LSUB(REG_ITMP1, REG_ITMP3, d);
1234 store_reg_to_var_int(iptr->dst, d);
1238 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1239 /* op1 = variable, val.i = constant */
1241 var = &(rd->locals[iptr->op1][TYPE_INT]);
1242 if (var->flags & INMEMORY) {
1244 M_LLD(s1, REG_SP, var->regoff * 8);
1247 M_IADD_IMM(s1, iptr->val.i, s1);
1248 if (var->flags & INMEMORY)
1249 M_LST(s1, REG_SP, var->regoff * 8);
1253 /* floating operations ************************************************/
1255 case ICMD_FNEG: /* ..., value ==> ..., - value */
1257 var_to_reg_flt(s1, src, REG_FTMP1);
1258 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1260 store_reg_to_var_flt(iptr->dst, d);
1263 case ICMD_DNEG: /* ..., value ==> ..., - value */
1265 var_to_reg_flt(s1, src, REG_FTMP1);
1266 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1268 store_reg_to_var_flt(iptr->dst, d);
1271 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1273 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1274 var_to_reg_flt(s2, src, REG_FTMP2);
1275 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1277 store_reg_to_var_flt(iptr->dst, d);
1280 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1282 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1283 var_to_reg_flt(s2, src, REG_FTMP2);
1284 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1286 store_reg_to_var_flt(iptr->dst, d);
1289 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1291 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1292 var_to_reg_flt(s2, src, REG_FTMP2);
1293 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1295 store_reg_to_var_flt(iptr->dst, d);
1298 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1300 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1301 var_to_reg_flt(s2, src, REG_FTMP2);
1302 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1304 store_reg_to_var_flt(iptr->dst, d);
1307 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1309 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1310 var_to_reg_flt(s2, src, REG_FTMP2);
1311 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1313 store_reg_to_var_flt(iptr->dst, d);
1316 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1318 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1319 var_to_reg_flt(s2, src, REG_FTMP2);
1320 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1322 store_reg_to_var_flt(iptr->dst, d);
1325 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1327 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1328 var_to_reg_flt(s2, src, REG_FTMP2);
1329 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1331 store_reg_to_var_flt(iptr->dst, d);
1334 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1336 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1337 var_to_reg_flt(s2, src, REG_FTMP2);
1338 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1340 store_reg_to_var_flt(iptr->dst, d);
1344 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1346 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1347 var_to_reg_flt(s2, src, REG_FTMP2);
1348 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1349 M_FDIV(s1,s2, REG_FTMP3);
1350 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1351 M_CVTLF(REG_FTMP3, REG_FTMP3);
1352 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1353 M_FSUB(s1, REG_FTMP3, d);
1354 store_reg_to_var_flt(iptr->dst, d);
1357 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1359 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1360 var_to_reg_flt(s2, src, REG_FTMP2);
1361 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1362 M_DDIV(s1,s2, REG_FTMP3);
1363 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1364 M_CVTLD(REG_FTMP3, REG_FTMP3);
1365 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1366 M_DSUB(s1, REG_FTMP3, d);
1367 store_reg_to_var_flt(iptr->dst, d);
1371 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1373 var_to_reg_int(s1, src, REG_ITMP1);
1374 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1377 store_reg_to_var_flt(iptr->dst, d);
1380 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1382 var_to_reg_int(s1, src, REG_ITMP1);
1383 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1386 store_reg_to_var_flt(iptr->dst, d);
1390 /* XXX these do not work correctly */
1392 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1394 var_to_reg_flt(s1, src, REG_FTMP1);
1395 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1396 M_TRUNCFI(s1, REG_FTMP1);
1397 M_MOVDI(REG_FTMP1, d);
1399 store_reg_to_var_int(iptr->dst, d);
1402 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1404 var_to_reg_flt(s1, src, REG_FTMP1);
1405 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1406 M_TRUNCDI(s1, REG_FTMP1);
1407 M_MOVDI(REG_FTMP1, d);
1409 store_reg_to_var_int(iptr->dst, d);
1412 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1414 var_to_reg_flt(s1, src, REG_FTMP1);
1415 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1416 M_TRUNCFL(s1, REG_FTMP1);
1417 M_MOVDL(REG_FTMP1, d);
1419 store_reg_to_var_int(iptr->dst, d);
1422 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1424 var_to_reg_flt(s1, src, REG_FTMP1);
1425 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1426 M_TRUNCDL(s1, REG_FTMP1);
1427 M_MOVDL(REG_FTMP1, d);
1429 store_reg_to_var_int(iptr->dst, d);
1433 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1435 var_to_reg_flt(s1, src, REG_FTMP1);
1436 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1438 store_reg_to_var_flt(iptr->dst, d);
1441 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1443 var_to_reg_flt(s1, src, REG_FTMP1);
1444 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1446 store_reg_to_var_flt(iptr->dst, d);
1449 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1451 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1452 var_to_reg_flt(s2, src, REG_FTMP2);
1453 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1456 M_LADD_IMM(REG_ZERO, 1, d);
1460 M_LSUB_IMM(REG_ZERO, 1, d);
1461 M_CMOVT(REG_ZERO, d);
1462 store_reg_to_var_int(iptr->dst, d);
1465 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1467 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1468 var_to_reg_flt(s2, src, REG_FTMP2);
1469 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1472 M_LADD_IMM(REG_ZERO, 1, d);
1476 M_LSUB_IMM(REG_ZERO, 1, d);
1477 M_CMOVT(REG_ZERO, d);
1478 store_reg_to_var_int(iptr->dst, d);
1481 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1483 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1484 var_to_reg_flt(s2, src, REG_FTMP2);
1485 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1488 M_LSUB_IMM(REG_ZERO, 1, d);
1492 M_LADD_IMM(REG_ZERO, 1, d);
1493 M_CMOVT(REG_ZERO, d);
1494 store_reg_to_var_int(iptr->dst, d);
1497 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1499 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1500 var_to_reg_flt(s2, src, REG_FTMP2);
1501 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1504 M_LSUB_IMM(REG_ZERO, 1, d);
1508 M_LADD_IMM(REG_ZERO, 1, d);
1509 M_CMOVT(REG_ZERO, d);
1510 store_reg_to_var_int(iptr->dst, d);
1514 /* memory operations **************************************************/
1516 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1518 var_to_reg_int(s1, src, REG_ITMP1);
1519 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1520 gen_nullptr_check(s1);
1521 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1522 store_reg_to_var_int(iptr->dst, d);
1525 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1527 var_to_reg_int(s1, src->prev, REG_ITMP1);
1528 var_to_reg_int(s2, src, REG_ITMP2);
1529 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1530 if (iptr->op1 == 0) {
1531 gen_nullptr_check(s1);
1534 M_AADD(s2, s1, REG_ITMP3);
1535 M_BLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1536 store_reg_to_var_int(iptr->dst, d);
1539 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1541 var_to_reg_int(s1, src->prev, REG_ITMP1);
1542 var_to_reg_int(s2, src, REG_ITMP2);
1543 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1544 if (iptr->op1 == 0) {
1545 gen_nullptr_check(s1);
1548 M_AADD(s2, s1, REG_ITMP3);
1549 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1550 M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1551 store_reg_to_var_int(iptr->dst, d);
1554 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1556 var_to_reg_int(s1, src->prev, REG_ITMP1);
1557 var_to_reg_int(s2, src, REG_ITMP2);
1558 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1559 if (iptr->op1 == 0) {
1560 gen_nullptr_check(s1);
1563 M_AADD(s2, s1, REG_ITMP3);
1564 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1565 M_SLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1566 store_reg_to_var_int(iptr->dst, d);
1569 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1571 var_to_reg_int(s1, src->prev, REG_ITMP1);
1572 var_to_reg_int(s2, src, REG_ITMP2);
1573 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1574 if (iptr->op1 == 0) {
1575 gen_nullptr_check(s1);
1578 M_ASLL_IMM(s2, 2, REG_ITMP3);
1579 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1580 M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
1581 store_reg_to_var_int(iptr->dst, d);
1584 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1586 var_to_reg_int(s1, src->prev, REG_ITMP1);
1587 var_to_reg_int(s2, src, REG_ITMP2);
1588 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1589 if (iptr->op1 == 0) {
1590 gen_nullptr_check(s1);
1593 M_ASLL_IMM(s2, 3, REG_ITMP3);
1594 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1595 M_LLD(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
1596 store_reg_to_var_int(iptr->dst, d);
1599 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1601 var_to_reg_int(s1, src->prev, REG_ITMP1);
1602 var_to_reg_int(s2, src, REG_ITMP2);
1603 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1604 if (iptr->op1 == 0) {
1605 gen_nullptr_check(s1);
1608 M_ASLL_IMM(s2, 2, REG_ITMP3);
1609 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1610 M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
1611 store_reg_to_var_flt(iptr->dst, d);
1614 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1616 var_to_reg_int(s1, src->prev, REG_ITMP1);
1617 var_to_reg_int(s2, src, REG_ITMP2);
1618 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1619 if (iptr->op1 == 0) {
1620 gen_nullptr_check(s1);
1623 M_ASLL_IMM(s2, 3, REG_ITMP3);
1624 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1625 M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
1626 store_reg_to_var_flt(iptr->dst, d);
1629 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1631 var_to_reg_int(s1, src->prev, REG_ITMP1);
1632 var_to_reg_int(s2, src, REG_ITMP2);
1633 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1634 if (iptr->op1 == 0) {
1635 gen_nullptr_check(s1);
1638 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1639 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1640 M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
1641 store_reg_to_var_int(iptr->dst, d);
1645 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1647 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1648 var_to_reg_int(s2, src->prev, REG_ITMP2);
1649 if (iptr->op1 == 0) {
1650 gen_nullptr_check(s1);
1653 M_AADD(s2, s1, REG_ITMP1);
1654 var_to_reg_int(s3, src, REG_ITMP3);
1655 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1658 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1659 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1661 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1662 var_to_reg_int(s2, src->prev, REG_ITMP2);
1663 if (iptr->op1 == 0) {
1664 gen_nullptr_check(s1);
1667 M_AADD(s2, s1, REG_ITMP1);
1668 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1669 var_to_reg_int(s3, src, REG_ITMP3);
1670 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1673 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1675 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1676 var_to_reg_int(s2, src->prev, REG_ITMP2);
1677 if (iptr->op1 == 0) {
1678 gen_nullptr_check(s1);
1681 M_ASLL_IMM(s2, 2, REG_ITMP2);
1682 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1683 var_to_reg_int(s3, src, REG_ITMP3);
1684 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1687 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1689 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1690 var_to_reg_int(s2, src->prev, REG_ITMP2);
1691 if (iptr->op1 == 0) {
1692 gen_nullptr_check(s1);
1695 M_ASLL_IMM(s2, 3, REG_ITMP2);
1696 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1697 var_to_reg_int(s3, src, REG_ITMP3);
1698 M_LST_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1701 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1703 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1704 var_to_reg_int(s2, src->prev, REG_ITMP2);
1705 if (iptr->op1 == 0) {
1706 gen_nullptr_check(s1);
1709 M_ASLL_IMM(s2, 2, REG_ITMP2);
1710 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1711 var_to_reg_flt(s3, src, REG_FTMP1);
1712 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1715 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1717 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1718 var_to_reg_int(s2, src->prev, REG_ITMP2);
1719 if (iptr->op1 == 0) {
1720 gen_nullptr_check(s1);
1723 M_ASLL_IMM(s2, 3, REG_ITMP2);
1724 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1725 var_to_reg_flt(s3, src, REG_FTMP1);
1726 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1730 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1732 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1733 var_to_reg_int(s2, src->prev, REG_ITMP2);
1734 if (iptr->op1 == 0) {
1735 gen_nullptr_check(s1);
1738 var_to_reg_int(s3, src, REG_ITMP3);
1740 M_MOV(s1, rd->argintregs[0]);
1741 M_MOV(s3, rd->argintregs[1]);
1742 disp = dseg_addaddress(cd, BUILTIN_canstore);
1743 M_ALD(REG_ITMP3, REG_PV, disp);
1744 M_JSR(REG_RA, REG_ITMP3);
1747 M_BEQZ(REG_RESULT, 0);
1748 codegen_addxstorerefs(cd, mcodeptr);
1751 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1752 var_to_reg_int(s2, src->prev, REG_ITMP2);
1753 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1754 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1755 var_to_reg_int(s3, src, REG_ITMP3);
1756 M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1760 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1762 var_to_reg_int(s1, src->prev, REG_ITMP1);
1763 var_to_reg_int(s2, src, REG_ITMP2);
1764 if (iptr->op1 == 0) {
1765 gen_nullptr_check(s1);
1768 M_AADD(s2, s1, REG_ITMP1);
1769 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1772 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1773 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1775 var_to_reg_int(s1, src->prev, REG_ITMP1);
1776 var_to_reg_int(s2, src, REG_ITMP2);
1777 if (iptr->op1 == 0) {
1778 gen_nullptr_check(s1);
1781 M_AADD(s2, s1, REG_ITMP1);
1782 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1783 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
1786 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1788 var_to_reg_int(s1, src->prev, REG_ITMP1);
1789 var_to_reg_int(s2, src, REG_ITMP2);
1790 if (iptr->op1 == 0) {
1791 gen_nullptr_check(s1);
1794 M_ASLL_IMM(s2, 2, REG_ITMP2);
1795 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1796 M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1799 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1801 var_to_reg_int(s1, src->prev, REG_ITMP1);
1802 var_to_reg_int(s2, src, REG_ITMP2);
1803 if (iptr->op1 == 0) {
1804 gen_nullptr_check(s1);
1807 M_ASLL_IMM(s2, 3, REG_ITMP2);
1808 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1809 M_LST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1812 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1814 var_to_reg_int(s1, src->prev, REG_ITMP1);
1815 var_to_reg_int(s2, src, REG_ITMP2);
1816 if (iptr->op1 == 0) {
1817 gen_nullptr_check(s1);
1820 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1821 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1822 M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1826 case ICMD_GETSTATIC: /* ... ==> ..., value */
1827 /* op1 = type, val.a = field address */
1829 if (iptr->val.a == NULL) {
1830 disp = dseg_addaddress(cd, NULL);
1832 codegen_addpatchref(cd, mcodeptr,
1833 PATCHER_get_putstatic,
1834 (unresolved_field *) iptr->target, disp);
1836 if (opt_showdisassemble) {
1841 fieldinfo *fi = iptr->val.a;
1843 disp = dseg_addaddress(cd, &(fi->value));
1845 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1846 codegen_addpatchref(cd, mcodeptr,
1847 PATCHER_clinit, fi->class, 0);
1849 if (opt_showdisassemble) {
1855 M_ALD(REG_ITMP1, REG_PV, disp);
1856 switch (iptr->op1) {
1858 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1859 M_ILD_INTERN(d, REG_ITMP1, 0);
1860 store_reg_to_var_int(iptr->dst, d);
1863 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1864 M_LLD_INTERN(d, REG_ITMP1, 0);
1865 store_reg_to_var_int(iptr->dst, d);
1868 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1869 M_ALD_INTERN(d, REG_ITMP1, 0);
1870 store_reg_to_var_int(iptr->dst, d);
1873 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1874 M_FLD_INTERN(d, REG_ITMP1, 0);
1875 store_reg_to_var_flt(iptr->dst, d);
1878 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1879 M_DLD_INTERN(d, REG_ITMP1, 0);
1880 store_reg_to_var_flt(iptr->dst, d);
1885 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1886 /* op1 = type, val.a = field address */
1888 if (iptr->val.a == NULL) {
1889 disp = dseg_addaddress(cd, NULL);
1891 codegen_addpatchref(cd, mcodeptr,
1892 PATCHER_get_putstatic,
1893 (unresolved_field *) iptr->target, disp);
1895 if (opt_showdisassemble) {
1900 fieldinfo *fi = iptr->val.a;
1902 disp = dseg_addaddress(cd, &(fi->value));
1904 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1905 codegen_addpatchref(cd, mcodeptr,
1906 PATCHER_clinit, fi->class, 0);
1908 if (opt_showdisassemble) {
1914 M_ALD(REG_ITMP1, REG_PV, disp);
1915 switch (iptr->op1) {
1917 var_to_reg_int(s2, src, REG_ITMP2);
1918 M_IST_INTERN(s2, REG_ITMP1, 0);
1921 var_to_reg_int(s2, src, REG_ITMP2);
1922 M_LST_INTERN(s2, REG_ITMP1, 0);
1925 var_to_reg_int(s2, src, REG_ITMP2);
1926 M_AST_INTERN(s2, REG_ITMP1, 0);
1929 var_to_reg_flt(s2, src, REG_FTMP2);
1930 M_FST_INTERN(s2, REG_ITMP1, 0);
1933 var_to_reg_flt(s2, src, REG_FTMP2);
1934 M_DST_INTERN(s2, REG_ITMP1, 0);
1939 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1940 /* val = value (in current instruction) */
1941 /* op1 = type, val.a = field address (in */
1942 /* following NOP) */
1944 if (iptr[1].val.a == NULL) {
1945 disp = dseg_addaddress(cd, NULL);
1947 codegen_addpatchref(cd, mcodeptr,
1948 PATCHER_get_putstatic,
1949 (unresolved_field *) iptr[1].target, disp);
1951 if (opt_showdisassemble) {
1956 fieldinfo *fi = iptr[1].val.a;
1958 disp = dseg_addaddress(cd, &(fi->value));
1960 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1961 codegen_addpatchref(cd, mcodeptr,
1962 PATCHER_clinit, fi->class, 0);
1964 if (opt_showdisassemble) {
1970 M_ALD(REG_ITMP1, REG_PV, disp);
1971 switch (iptr->op1) {
1973 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1976 M_LST_INTERN(REG_ZERO, REG_ITMP1, 0);
1979 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1982 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1985 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1991 case ICMD_GETFIELD: /* ... ==> ..., value */
1992 /* op1 = type, val.i = field offset */
1994 var_to_reg_int(s1, src, REG_ITMP1);
1995 gen_nullptr_check(s1);
1997 if (iptr->val.a == NULL) {
1998 codegen_addpatchref(cd, mcodeptr,
1999 PATCHER_get_putfield,
2000 (unresolved_field *) iptr->target, 0);
2002 if (opt_showdisassemble) {
2009 a = ((fieldinfo *) (iptr->val.a))->offset;
2012 switch (iptr->op1) {
2014 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2016 store_reg_to_var_int(iptr->dst, d);
2019 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2021 store_reg_to_var_int(iptr->dst, d);
2024 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2026 store_reg_to_var_int(iptr->dst, d);
2029 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2031 store_reg_to_var_flt(iptr->dst, d);
2034 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2036 store_reg_to_var_flt(iptr->dst, d);
2041 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2042 /* op1 = type, val.a = field address */
2044 var_to_reg_int(s1, src->prev, REG_ITMP1);
2045 gen_nullptr_check(s1);
2047 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2048 var_to_reg_int(s2, src, REG_ITMP2);
2050 var_to_reg_flt(s2, src, REG_FTMP2);
2053 if (iptr->val.a == NULL) {
2054 codegen_addpatchref(cd, mcodeptr,
2055 PATCHER_get_putfield,
2056 (unresolved_field *) iptr->target, 0);
2058 if (opt_showdisassemble) {
2065 a = ((fieldinfo *) (iptr->val.a))->offset;
2068 switch (iptr->op1) {
2087 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2088 /* val = value (in current instruction) */
2089 /* op1 = type, val.a = field address (in */
2090 /* following NOP) */
2092 var_to_reg_int(s1, src, REG_ITMP1);
2093 gen_nullptr_check(s1);
2095 if (iptr[1].val.a == NULL) {
2096 codegen_addpatchref(cd, mcodeptr,
2097 PATCHER_get_putfield,
2098 (unresolved_field *) iptr[1].target, 0);
2100 if (opt_showdisassemble) {
2107 a = ((fieldinfo *) (iptr[1].val.a))->offset;
2110 switch (iptr[1].op1) {
2112 M_IST(REG_ZERO, s1, a);
2115 M_LST(REG_ZERO, s1, a);
2118 M_AST(REG_ZERO, s1, a);
2121 M_FST(REG_ZERO, s1, a);
2124 M_DST(REG_ZERO, s1, a);
2130 /* branch operations **************************************************/
2132 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2134 var_to_reg_int(s1, src, REG_ITMP1);
2135 M_INTMOVE(s1, REG_ITMP1_XPTR);
2137 #ifdef ENABLE_VERIFIER
2139 codegen_addpatchref(cd, mcodeptr,
2140 PATCHER_athrow_areturn,
2141 (unresolved_class *) iptr->val.a, 0);
2143 if (opt_showdisassemble) {
2147 #endif /* ENABLE_VERIFIER */
2149 disp = dseg_addaddress(cd, asm_handle_exception);
2150 M_ALD(REG_ITMP2, REG_PV, disp);
2151 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2153 M_NOP; /* nop ensures that XPC is less than the end */
2154 /* of basic block */
2158 case ICMD_GOTO: /* ... ==> ... */
2159 /* op1 = target JavaVM pc */
2161 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2166 case ICMD_JSR: /* ... ==> ... */
2167 /* op1 = target JavaVM pc */
2169 dseg_addtarget(cd, (basicblock *) iptr->target);
2170 M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
2171 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2175 case ICMD_RET: /* ... ==> ... */
2176 /* op1 = local variable */
2177 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2178 if (var->flags & INMEMORY) {
2179 M_ALD(REG_ITMP1, REG_SP, var->regoff * 8);
2187 case ICMD_IFNULL: /* ..., value ==> ... */
2188 /* op1 = target JavaVM pc */
2190 var_to_reg_int(s1, src, REG_ITMP1);
2192 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2196 case ICMD_IFNONNULL: /* ..., value ==> ... */
2197 /* op1 = target JavaVM pc */
2199 var_to_reg_int(s1, src, REG_ITMP1);
2201 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2205 case ICMD_IFEQ: /* ..., value ==> ... */
2206 /* op1 = target JavaVM pc, val.i = constant */
2208 var_to_reg_int(s1, src, REG_ITMP1);
2209 if (iptr->val.i == 0) {
2212 ICONST(REG_ITMP2, iptr->val.i);
2213 M_BEQ(s1, REG_ITMP2, 0);
2215 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2219 case ICMD_IFLT: /* ..., value ==> ... */
2220 /* op1 = target JavaVM pc, val.i = constant */
2222 var_to_reg_int(s1, src, REG_ITMP1);
2223 if (iptr->val.i == 0) {
2226 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2227 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2229 ICONST(REG_ITMP2, iptr->val.i);
2230 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2232 M_BNEZ(REG_ITMP1, 0);
2234 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2238 case ICMD_IFLE: /* ..., value ==> ... */
2239 /* op1 = target JavaVM pc, val.i = constant */
2241 var_to_reg_int(s1, src, REG_ITMP1);
2242 if (iptr->val.i == 0) {
2246 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2247 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2248 M_BNEZ(REG_ITMP1, 0);
2251 ICONST(REG_ITMP2, iptr->val.i);
2252 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2253 M_BEQZ(REG_ITMP1, 0);
2256 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2260 case ICMD_IFNE: /* ..., value ==> ... */
2261 /* op1 = target JavaVM pc, val.i = constant */
2263 var_to_reg_int(s1, src, REG_ITMP1);
2264 if (iptr->val.i == 0) {
2268 ICONST(REG_ITMP2, iptr->val.i);
2269 M_BNE(s1, REG_ITMP2, 0);
2271 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2275 case ICMD_IFGT: /* ..., value ==> ... */
2276 /* op1 = target JavaVM pc, val.i = constant */
2278 var_to_reg_int(s1, src, REG_ITMP1);
2279 if (iptr->val.i == 0) {
2283 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2284 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2285 M_BEQZ(REG_ITMP1, 0);
2288 ICONST(REG_ITMP2, iptr->val.i);
2289 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2290 M_BNEZ(REG_ITMP1, 0);
2293 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2297 case ICMD_IFGE: /* ..., value ==> ... */
2298 /* op1 = target JavaVM pc, val.i = constant */
2300 var_to_reg_int(s1, src, REG_ITMP1);
2301 if (iptr->val.i == 0) {
2305 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2306 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2309 ICONST(REG_ITMP2, iptr->val.i);
2310 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2312 M_BEQZ(REG_ITMP1, 0);
2314 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2318 case ICMD_IF_LEQ: /* ..., value ==> ... */
2319 /* op1 = target JavaVM pc, val.l = constant */
2321 var_to_reg_int(s1, src, REG_ITMP1);
2322 if (iptr->val.l == 0) {
2326 LCONST(REG_ITMP2, iptr->val.l);
2327 M_BEQ(s1, REG_ITMP2, 0);
2329 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2333 case ICMD_IF_LLT: /* ..., value ==> ... */
2334 /* op1 = target JavaVM pc, val.l = constant */
2336 var_to_reg_int(s1, src, REG_ITMP1);
2337 if (iptr->val.l == 0) {
2341 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2342 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2345 LCONST(REG_ITMP2, iptr->val.l);
2346 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2348 M_BNEZ(REG_ITMP1, 0);
2350 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2354 case ICMD_IF_LLE: /* ..., value ==> ... */
2355 /* op1 = target JavaVM pc, val.l = constant */
2357 var_to_reg_int(s1, src, REG_ITMP1);
2358 if (iptr->val.l == 0) {
2362 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2363 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2364 M_BNEZ(REG_ITMP1, 0);
2367 LCONST(REG_ITMP2, iptr->val.l);
2368 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2369 M_BEQZ(REG_ITMP1, 0);
2372 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2376 case ICMD_IF_LNE: /* ..., value ==> ... */
2377 /* op1 = target JavaVM pc, val.l = constant */
2379 var_to_reg_int(s1, src, REG_ITMP1);
2380 if (iptr->val.l == 0) {
2384 LCONST(REG_ITMP2, iptr->val.l);
2385 M_BNE(s1, REG_ITMP2, 0);
2387 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2391 case ICMD_IF_LGT: /* ..., value ==> ... */
2392 /* op1 = target JavaVM pc, val.l = constant */
2394 var_to_reg_int(s1, src, REG_ITMP1);
2395 if (iptr->val.l == 0) {
2399 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2400 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2401 M_BEQZ(REG_ITMP1, 0);
2404 LCONST(REG_ITMP2, iptr->val.l);
2405 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2406 M_BNEZ(REG_ITMP1, 0);
2409 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2413 case ICMD_IF_LGE: /* ..., value ==> ... */
2414 /* op1 = target JavaVM pc, val.l = constant */
2416 var_to_reg_int(s1, src, REG_ITMP1);
2417 if (iptr->val.l == 0) {
2421 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2422 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2425 LCONST(REG_ITMP2, iptr->val.l);
2426 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2428 M_BEQZ(REG_ITMP1, 0);
2430 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2434 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2435 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2436 case ICMD_IF_ACMPEQ:
2438 var_to_reg_int(s1, src->prev, REG_ITMP1);
2439 var_to_reg_int(s2, src, REG_ITMP2);
2441 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2445 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2446 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2447 case ICMD_IF_ACMPNE:
2449 var_to_reg_int(s1, src->prev, REG_ITMP1);
2450 var_to_reg_int(s2, src, REG_ITMP2);
2452 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2456 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2457 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2459 var_to_reg_int(s1, src->prev, REG_ITMP1);
2460 var_to_reg_int(s2, src, REG_ITMP2);
2461 M_CMPLT(s1, s2, REG_ITMP1);
2462 M_BNEZ(REG_ITMP1, 0);
2463 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2467 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2468 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2470 var_to_reg_int(s1, src->prev, REG_ITMP1);
2471 var_to_reg_int(s2, src, REG_ITMP2);
2472 M_CMPGT(s1, s2, REG_ITMP1);
2473 M_BNEZ(REG_ITMP1, 0);
2474 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2478 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2479 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2481 var_to_reg_int(s1, src->prev, REG_ITMP1);
2482 var_to_reg_int(s2, src, REG_ITMP2);
2483 M_CMPGT(s1, s2, REG_ITMP1);
2484 M_BEQZ(REG_ITMP1, 0);
2485 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2489 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2490 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2492 var_to_reg_int(s1, src->prev, REG_ITMP1);
2493 var_to_reg_int(s2, src, REG_ITMP2);
2494 M_CMPLT(s1, s2, REG_ITMP1);
2495 M_BEQZ(REG_ITMP1, 0);
2496 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2500 #ifdef CONDITIONAL_LOADCONST
2501 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2503 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2506 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2507 /* val.i = constant */
2509 var_to_reg_int(s1, src, REG_ITMP1);
2510 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2512 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2513 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2514 M_CMPEQ(s1, REG_ZERO, d);
2515 store_reg_to_var_int(iptr->dst, d);
2518 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2519 M_CMPEQ(s1, REG_ZERO, d);
2521 store_reg_to_var_int(iptr->dst, d);
2525 M_MOV(s1, REG_ITMP1);
2528 ICONST(d, iptr[1].val.i);
2530 if ((s3 >= 0) && (s3 <= 255)) {
2531 M_CMOVEQ_IMM(s1, s3, d);
2533 ICONST(REG_ITMP3, s3);
2534 M_CMOVEQ(s1, REG_ITMP3, d);
2536 store_reg_to_var_int(iptr->dst, d);
2539 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2540 /* val.i = constant */
2542 var_to_reg_int(s1, src, REG_ITMP1);
2543 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2545 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2546 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2547 M_CMPEQ(s1, REG_ZERO, d);
2548 store_reg_to_var_int(iptr->dst, d);
2551 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2552 M_CMPEQ(s1, REG_ZERO, d);
2554 store_reg_to_var_int(iptr->dst, d);
2558 M_MOV(s1, REG_ITMP1);
2561 ICONST(d, iptr[1].val.i);
2563 if ((s3 >= 0) && (s3 <= 255)) {
2564 M_CMOVNE_IMM(s1, s3, d);
2566 ICONST(REG_ITMP3, s3);
2567 M_CMOVNE(s1, REG_ITMP3, d);
2569 store_reg_to_var_int(iptr->dst, d);
2572 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2573 /* val.i = constant */
2575 var_to_reg_int(s1, src, REG_ITMP1);
2576 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2578 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2579 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2580 M_CMPLT(s1, REG_ZERO, d);
2581 store_reg_to_var_int(iptr->dst, d);
2584 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2585 M_CMPLE(REG_ZERO, s1, d);
2586 store_reg_to_var_int(iptr->dst, d);
2590 M_MOV(s1, REG_ITMP1);
2593 ICONST(d, iptr[1].val.i);
2595 if ((s3 >= 0) && (s3 <= 255)) {
2596 M_CMOVLT_IMM(s1, s3, d);
2598 ICONST(REG_ITMP3, s3);
2599 M_CMOVLT(s1, REG_ITMP3, d);
2601 store_reg_to_var_int(iptr->dst, d);
2604 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2605 /* val.i = constant */
2607 var_to_reg_int(s1, src, REG_ITMP1);
2608 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2610 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2611 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2612 M_CMPLE(REG_ZERO, s1, d);
2613 store_reg_to_var_int(iptr->dst, d);
2616 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2617 M_CMPLT(s1, REG_ZERO, d);
2618 store_reg_to_var_int(iptr->dst, d);
2622 M_MOV(s1, REG_ITMP1);
2625 ICONST(d, iptr[1].val.i);
2627 if ((s3 >= 0) && (s3 <= 255)) {
2628 M_CMOVGE_IMM(s1, s3, d);
2630 ICONST(REG_ITMP3, s3);
2631 M_CMOVGE(s1, REG_ITMP3, d);
2633 store_reg_to_var_int(iptr->dst, d);
2636 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2637 /* val.i = constant */
2639 var_to_reg_int(s1, src, REG_ITMP1);
2640 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2642 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2643 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2644 M_CMPLT(REG_ZERO, s1, d);
2645 store_reg_to_var_int(iptr->dst, d);
2648 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2649 M_CMPLE(s1, REG_ZERO, d);
2650 store_reg_to_var_int(iptr->dst, d);
2654 M_MOV(s1, REG_ITMP1);
2657 ICONST(d, iptr[1].val.i);
2659 if ((s3 >= 0) && (s3 <= 255)) {
2660 M_CMOVGT_IMM(s1, s3, d);
2662 ICONST(REG_ITMP3, s3);
2663 M_CMOVGT(s1, REG_ITMP3, d);
2665 store_reg_to_var_int(iptr->dst, d);
2668 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2669 /* val.i = constant */
2671 var_to_reg_int(s1, src, REG_ITMP1);
2672 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2674 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2675 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2676 M_CMPLE(s1, REG_ZERO, d);
2677 store_reg_to_var_int(iptr->dst, d);
2680 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2681 M_CMPLT(REG_ZERO, s1, d);
2682 store_reg_to_var_int(iptr->dst, d);
2686 M_MOV(s1, REG_ITMP1);
2689 ICONST(d, iptr[1].val.i);
2691 if ((s3 >= 0) && (s3 <= 255)) {
2692 M_CMOVLE_IMM(s1, s3, d);
2694 ICONST(REG_ITMP3, s3);
2695 M_CMOVLE(s1, REG_ITMP3, d);
2697 store_reg_to_var_int(iptr->dst, d);
2702 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2705 var_to_reg_int(s1, src, REG_RESULT);
2706 M_INTMOVE(s1, REG_RESULT);
2707 goto nowperformreturn;
2709 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2711 var_to_reg_int(s1, src, REG_RESULT);
2712 M_INTMOVE(s1, REG_RESULT);
2714 #ifdef ENABLE_VERIFIER
2716 codegen_addpatchref(cd, mcodeptr,
2717 PATCHER_athrow_areturn,
2718 (unresolved_class *) iptr->val.a, 0);
2720 if (opt_showdisassemble) {
2724 #endif /* ENABLE_VERIFIER */
2725 goto nowperformreturn;
2727 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2729 var_to_reg_flt(s1, src, REG_FRESULT);
2731 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2732 M_TFLTMOVE(t, s1, REG_FRESULT);
2734 goto nowperformreturn;
2736 case ICMD_RETURN: /* ... ==> ... */
2742 p = parentargs_base;
2744 /* call trace function */
2747 M_LDA(REG_SP, REG_SP, -3 * 8);
2748 M_LST(REG_RA, REG_SP, 0 * 8);
2749 M_LST(REG_RESULT, REG_SP, 1 * 8);
2750 M_DST(REG_FRESULT, REG_SP, 2 * 8);
2752 disp = dseg_addaddress(cd, m);
2753 M_ALD(rd->argintregs[0], REG_PV, disp);
2754 M_MOV(REG_RESULT, rd->argintregs[1]);
2755 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2756 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
2758 disp = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2759 M_ALD(REG_ITMP3, REG_PV, disp);
2760 M_JSR(REG_RA, REG_ITMP3);
2763 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
2764 M_LLD(REG_RESULT, REG_SP, 1 * 8);
2765 M_LLD(REG_RA, REG_SP, 0 * 8);
2766 M_LDA(REG_SP, REG_SP, 3 * 8);
2769 #if defined(USE_THREADS)
2770 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2771 disp = dseg_addaddress(cd, (void *) builtin_monitorexit);
2772 M_ALD(REG_ITMP3, REG_PV, disp);
2774 /* we need to save the proper return value */
2776 switch (iptr->opc) {
2780 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2781 M_JSR(REG_RA, REG_ITMP3);
2782 M_LST(REG_RESULT, REG_SP, rd->memuse * 8); /* delay slot */
2786 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2787 M_JSR(REG_RA, REG_ITMP3);
2788 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8); /* delay slot */
2791 M_JSR(REG_RA, REG_ITMP3);
2792 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8); /* delay*/
2796 /* and now restore the proper return value */
2798 switch (iptr->opc) {
2802 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
2806 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
2812 /* restore return address */
2814 if (!m->isleafmethod) {
2815 p--; M_ALD(REG_RA, REG_SP, p * 8);
2818 /* restore saved registers */
2820 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2821 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
2823 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2824 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2827 /* deallocate stack and return */
2829 if (parentargs_base) {
2832 disp = parentargs_base * 8;
2833 lo = (short) (disp);
2834 hi = (short) (((disp) - lo) >> 16);
2838 M_LADD_IMM(REG_SP, lo, REG_SP); /* delay slot */
2840 M_LUI(REG_ITMP3,hi);
2841 M_LADD_IMM(REG_ITMP3,lo,REG_ITMP3);
2843 M_LADD(REG_ITMP3,REG_SP,REG_SP); /* delay slot */
2856 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2861 tptr = (void **) iptr->target;
2863 s4ptr = iptr->val.a;
2864 l = s4ptr[1]; /* low */
2865 i = s4ptr[2]; /* high */
2867 var_to_reg_int(s1, src, REG_ITMP1);
2869 {M_INTMOVE(s1, REG_ITMP1);}
2870 else if (l <= 32768) {
2871 M_IADD_IMM(s1, -l, REG_ITMP1);
2874 ICONST(REG_ITMP2, l);
2875 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2881 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
2882 M_BEQZ(REG_ITMP2, 0);
2883 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2884 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
2886 /* build jump table top down and use address of lowest entry */
2888 /* s4ptr += 3 + i; */
2892 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2893 dseg_addtarget(cd, (basicblock *) tptr[0]);
2898 /* length of dataseg after last dseg_addtarget is used by load */
2900 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2901 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2908 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2910 s4 i, /*l, */val, *s4ptr;
2913 tptr = (void **) iptr->target;
2915 s4ptr = iptr->val.a;
2916 /*l = s4ptr[0];*/ /* default */
2917 i = s4ptr[1]; /* count */
2919 MCODECHECK((i<<2)+8);
2920 var_to_reg_int(s1, src, REG_ITMP1);
2926 ICONST(REG_ITMP2, val);
2927 M_BEQ(s1, REG_ITMP2, 0);
2928 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2933 tptr = (void **) iptr->target;
2934 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2941 case ICMD_BUILTIN: /* ..., arg1 ==> ... */
2942 /* op1 = arg count val.a = builtintable entry */
2948 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2949 /* op1 = arg count, val.a = method pointer */
2951 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2952 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2953 case ICMD_INVOKEINTERFACE:
2958 unresolved_method *um = iptr->target;
2959 md = um->methodref->parseddesc.md;
2961 md = lm->parseddesc;
2965 s3 = md->paramcount;
2967 MCODECHECK((s3 << 1) + 64);
2969 /* copy arguments to registers or stack location */
2971 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2972 if (src->varkind == ARGVAR)
2974 if (IS_INT_LNG_TYPE(src->type)) {
2975 if (!md->params[s3].inmemory) {
2976 s1 = rd->argintregs[md->params[s3].regoff];
2977 var_to_reg_int(d, src, s1);
2980 var_to_reg_int(d, src, REG_ITMP1);
2981 M_LST(d, REG_SP, md->params[s3].regoff * 8);
2985 if (!md->params[s3].inmemory) {
2986 s1 = rd->argfltregs[md->params[s3].regoff];
2987 var_to_reg_flt(d, src, s1);
2988 M_TFLTMOVE(src->type, d, s1);
2990 var_to_reg_flt(d, src, REG_FTMP1);
2991 M_DST(d, REG_SP, md->params[s3].regoff * 8);
2996 switch (iptr->opc) {
2998 disp = dseg_addaddress(cd, bte->fp);
2999 d = md->returntype.type;
3001 M_ALD(REG_ITMP3, REG_PV, disp); /* built-in-function pointer */
3002 M_JSR(REG_RA, REG_ITMP3);
3004 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3005 M_LDA(REG_PV, REG_RA, -disp);
3007 /* if op1 == true, we need to check for an exception */
3009 if (iptr->op1 == true) {
3010 M_BEQZ(REG_RESULT, 0);
3011 codegen_addxexceptionrefs(cd, mcodeptr);
3016 case ICMD_INVOKESPECIAL:
3017 M_BEQZ(rd->argintregs[0], 0);
3018 codegen_addxnullrefs(cd, mcodeptr);
3022 case ICMD_INVOKESTATIC:
3024 unresolved_method *um = iptr->target;
3026 disp = dseg_addaddress(cd, NULL);
3028 codegen_addpatchref(cd, mcodeptr,
3029 PATCHER_invokestatic_special, um, disp);
3031 if (opt_showdisassemble) {
3035 d = um->methodref->parseddesc.md->returntype.type;
3038 disp = dseg_addaddress(cd, lm->stubroutine);
3039 d = lm->parseddesc->returntype.type;
3042 M_ALD(REG_PV, REG_PV, disp); /* method pointer in pv */
3043 M_JSR(REG_RA, REG_PV);
3045 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3046 M_LDA(REG_PV, REG_RA, -disp);
3049 case ICMD_INVOKEVIRTUAL:
3050 gen_nullptr_check(rd->argintregs[0]);
3053 unresolved_method *um = iptr->target;
3055 codegen_addpatchref(cd, mcodeptr,
3056 PATCHER_invokevirtual, um, 0);
3058 if (opt_showdisassemble) {
3063 d = um->methodref->parseddesc.md->returntype.type;
3066 s1 = OFFSET(vftbl_t, table[0]) +
3067 sizeof(methodptr) * lm->vftblindex;
3068 d = lm->parseddesc->returntype.type;
3071 M_ALD(REG_METHODPTR, rd->argintregs[0],
3072 OFFSET(java_objectheader, vftbl));
3073 M_ALD(REG_PV, REG_METHODPTR, s1);
3074 M_JSR(REG_RA, REG_PV);
3076 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3077 M_LDA(REG_PV, REG_RA, -disp);
3080 case ICMD_INVOKEINTERFACE:
3081 gen_nullptr_check(rd->argintregs[0]);
3084 unresolved_method *um = iptr->target;
3086 codegen_addpatchref(cd, mcodeptr,
3087 PATCHER_invokeinterface, um, 0);
3089 if (opt_showdisassemble) {
3095 d = um->methodref->parseddesc.md->returntype.type;
3098 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3099 sizeof(methodptr*) * lm->class->index;
3101 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3103 d = lm->parseddesc->returntype.type;
3106 M_ALD(REG_METHODPTR, rd->argintregs[0],
3107 OFFSET(java_objectheader, vftbl));
3108 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3109 M_ALD(REG_PV, REG_METHODPTR, s2);
3110 M_JSR(REG_RA, REG_PV);
3112 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3113 M_LDA(REG_PV, REG_RA, -disp);
3117 /* d contains return type */
3119 if (d != TYPE_VOID) {
3120 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3121 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3122 M_INTMOVE(REG_RESULT, s1);
3123 store_reg_to_var_int(iptr->dst, s1);
3125 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3126 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3127 store_reg_to_var_flt(iptr->dst, s1);
3133 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3134 /* op1: 0 == array, 1 == class */
3135 /* val.a: (classinfo*) superclass */
3137 /* superclass is an interface:
3139 * OK if ((sub == NULL) ||
3140 * (sub->vftbl->interfacetablelength > super->index) &&
3141 * (sub->vftbl->interfacetable[-super->index] != NULL));
3143 * superclass is a class:
3145 * OK if ((sub == NULL) || (0
3146 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3147 * super->vftbl->diffvall));
3150 if (iptr->op1 == 1) {
3152 vftbl_t *supervftbl;
3155 super = (classinfo *) iptr->val.a;
3162 superindex = super->index;
3163 supervftbl = super->vftbl;
3166 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3167 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3170 var_to_reg_int(s1, src, REG_ITMP1);
3172 /* calculate interface checkcast code size */
3176 s2 += (opt_showdisassemble ? 2 : 0);
3178 /* calculate class checkcast code size */
3180 s3 = 10 /* 10 + (s1 == REG_ITMP1) */;
3182 s3 += (opt_showdisassemble ? 2 : 0);
3184 /* if class is not resolved, check which code to call */
3187 M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
3190 disp = dseg_adds4(cd, 0); /* super->flags */
3192 codegen_addpatchref(cd, mcodeptr,
3193 PATCHER_checkcast_instanceof_flags,
3194 (constant_classref *) iptr->target,
3197 if (opt_showdisassemble) {
3201 /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
3202 M_ILD(REG_ITMP2, REG_PV, disp);
3203 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3204 M_BEQZ(REG_ITMP2, 1 + s2 + 2);
3208 /* interface checkcast code */
3210 if (!super || super->flags & ACC_INTERFACE) {
3216 codegen_addpatchref(cd, mcodeptr,
3217 PATCHER_checkcast_instanceof_interface,
3218 (constant_classref *) iptr->target,
3221 if (opt_showdisassemble) {
3226 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3227 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3228 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3229 M_BLEZ(REG_ITMP3, 0);
3230 codegen_addxcastrefs(cd, mcodeptr);
3232 M_ALD(REG_ITMP3, REG_ITMP2,
3233 OFFSET(vftbl_t, interfacetable[0]) -
3234 superindex * sizeof(methodptr*));
3235 M_BEQZ(REG_ITMP3, 0);
3236 codegen_addxcastrefs(cd, mcodeptr);
3245 /* class checkcast code */
3247 if (!super || !(super->flags & ACC_INTERFACE)) {
3248 disp = dseg_addaddress(cd, (void *) supervftbl);
3255 codegen_addpatchref(cd, mcodeptr,
3256 PATCHER_checkcast_instanceof_class,
3257 (constant_classref *) iptr->target,
3260 if (opt_showdisassemble) {
3265 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3266 M_ALD(REG_ITMP3, REG_PV, disp);
3267 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3268 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3270 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3271 /* if (s1 != REG_ITMP1) { */
3272 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3273 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3274 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3275 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3277 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3279 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3280 M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3281 M_ALD(REG_ITMP3, REG_PV, disp);
3282 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3283 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3284 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3287 M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3288 M_BNEZ(REG_ITMP3, 0);
3289 codegen_addxcastrefs(cd, mcodeptr);
3292 d = reg_of_var(rd, iptr->dst, s1);
3295 var_to_reg_int(s1, src, rd->argintregs[0]);
3296 M_INTMOVE(s1, rd->argintregs[0]);
3298 disp = dseg_addaddress(cd, iptr->val.a);
3300 if (iptr->val.a == NULL) {
3301 codegen_addpatchref(cd, mcodeptr,
3302 PATCHER_builtin_arraycheckcast,
3303 (constant_classref *) iptr->target,
3306 if (opt_showdisassemble) {
3311 M_ALD(rd->argintregs[1], REG_PV, disp);
3312 disp = dseg_addaddress(cd, BUILTIN_arraycheckcast);
3313 M_ALD(REG_ITMP3, REG_PV, disp);
3314 M_JSR(REG_RA, REG_ITMP3);
3317 M_BEQZ(REG_RESULT, 0);
3318 codegen_addxcastrefs(cd, mcodeptr);
3321 var_to_reg_int(s1, src, REG_ITMP1);
3322 d = reg_of_var(rd, iptr->dst, s1);
3325 store_reg_to_var_int(iptr->dst, d);
3328 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3329 /* op1: 0 == array, 1 == class */
3330 /* val.a: (classinfo*) superclass */
3332 /* superclass is an interface:
3334 * return (sub != NULL) &&
3335 * (sub->vftbl->interfacetablelength > super->index) &&
3336 * (sub->vftbl->interfacetable[-super->index] != NULL);
3338 * superclass is a class:
3340 * return ((sub != NULL) && (0
3341 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3342 * super->vftbl->diffvall));
3347 vftbl_t *supervftbl;
3350 super = (classinfo *) iptr->val.a;
3357 superindex = super->index;
3358 supervftbl = super->vftbl;
3361 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3362 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3365 var_to_reg_int(s1, src, REG_ITMP1);
3366 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3368 M_MOV(s1, REG_ITMP1);
3372 /* calculate interface instanceof code size */
3376 s2 += (opt_showdisassemble ? 2 : 0);
3378 /* calculate class instanceof code size */
3382 s3 += (opt_showdisassemble ? 2 : 0);
3386 /* if class is not resolved, check which code to call */
3389 M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
3392 disp = dseg_adds4(cd, 0); /* super->flags */
3394 codegen_addpatchref(cd, mcodeptr,
3395 PATCHER_checkcast_instanceof_flags,
3396 (constant_classref *) iptr->target, disp);
3398 if (opt_showdisassemble) {
3402 /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
3403 M_ILD(REG_ITMP3, REG_PV, disp);
3404 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
3405 M_BEQZ(REG_ITMP3, 1 + s2 + 2);
3409 /* interface instanceof code */
3411 if (!super || (super->flags & ACC_INTERFACE)) {
3417 codegen_addpatchref(cd, mcodeptr,
3418 PATCHER_checkcast_instanceof_interface,
3419 (constant_classref *) iptr->target, 0);
3421 if (opt_showdisassemble) {
3426 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3427 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3428 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3429 M_BLEZ(REG_ITMP3, 3);
3431 M_ALD(REG_ITMP1, REG_ITMP1,
3432 OFFSET(vftbl_t, interfacetable[0]) -
3433 superindex * sizeof(methodptr*));
3434 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3442 /* class instanceof code */
3444 if (!super || !(super->flags & ACC_INTERFACE)) {
3445 disp = dseg_addaddress(cd, supervftbl);
3452 codegen_addpatchref(cd, mcodeptr,
3453 PATCHER_checkcast_instanceof_class,
3454 (constant_classref *) iptr->target,
3457 if (opt_showdisassemble) {
3462 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3463 M_ALD(REG_ITMP2, REG_PV, disp);
3464 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3465 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3467 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3468 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3469 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3470 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3471 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3473 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3474 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3477 store_reg_to_var_int(iptr->dst, d);
3481 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3482 /* op1 = dimension, val.a = class */
3484 /* check for negative sizes and copy sizes to stack if necessary */
3486 MCODECHECK((iptr->op1 << 1) + 64);
3488 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3489 /* copy SAVEDVAR sizes to stack */
3491 if (src->varkind != ARGVAR) {
3492 var_to_reg_int(s2, src, REG_ITMP1);
3493 M_LST(s2, REG_SP, s1 * 8);
3497 /* a0 = dimension count */
3499 ICONST(rd->argintregs[0], iptr->op1);
3501 /* is patcher function set? */
3503 if (iptr->val.a == NULL) {
3504 disp = dseg_addaddress(cd, NULL);
3506 codegen_addpatchref(cd, mcodeptr,
3507 PATCHER_builtin_multianewarray,
3508 (constant_classref *) iptr->target,
3511 if (opt_showdisassemble) {
3516 disp = dseg_addaddress(cd, iptr->val.a);
3519 /* a1 = arraydescriptor */
3521 M_ALD(rd->argintregs[1], REG_PV, disp);
3523 /* a2 = pointer to dimensions = stack pointer */
3525 M_INTMOVE(REG_SP, rd->argintregs[2]);
3527 disp = dseg_addaddress(cd, BUILTIN_multianewarray);
3528 M_ALD(REG_ITMP3, REG_PV, disp);
3529 M_JSR(REG_RA, REG_ITMP3);
3532 /* check for exception before result assignment */
3534 M_BEQZ(REG_RESULT, 0);
3535 codegen_addxexceptionrefs(cd, mcodeptr);
3538 d = reg_of_var(rd, iptr->dst, REG_RESULT);
3539 M_INTMOVE(REG_RESULT, d);
3540 store_reg_to_var_int(iptr->dst, d);
3544 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3548 } /* for instruction */
3550 /* copy values to interface registers */
3552 src = bptr->outstack;
3553 len = bptr->outdepth;
3555 #if defined(ENABLE_LSRA)
3560 if ((src->varkind != STACKVAR)) {
3562 if (IS_FLT_DBL_TYPE(s2)) {
3563 var_to_reg_flt(s1, src, REG_FTMP1);
3564 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3565 M_TFLTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3568 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3572 var_to_reg_int(s1, src, REG_ITMP1);
3573 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3574 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3577 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3584 /* At the end of a basic block we may have to append some nops,
3585 because the patcher stub calling code might be longer than the
3586 actual instruction. So codepatching does not change the
3587 following block unintentionally. */
3589 if ((u1 *) mcodeptr < cd->lastmcodeptr) {
3590 while ((u1 *) mcodeptr < cd->lastmcodeptr) {
3595 } /* if (bptr -> flags >= BBREACHED) */
3596 } /* for basic block */
3598 dseg_createlinenumbertable(cd);
3604 /* generate ArithmeticException stubs */
3608 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3609 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3611 (u1 *) mcodeptr - cd->mcodebase);
3615 if (xcodeptr != NULL) {
3616 M_BR(xcodeptr - mcodeptr);
3617 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3620 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3622 xcodeptr = mcodeptr;
3624 M_MOV(REG_PV, rd->argintregs[0]);
3625 M_MOV(REG_SP, rd->argintregs[1]);
3627 if (m->isleafmethod)
3628 M_MOV(REG_RA, rd->argintregs[2]);
3630 M_ALD(rd->argintregs[2],
3631 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3633 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3635 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3636 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3638 if (m->isleafmethod)
3639 M_AST(REG_RA, REG_SP, 1 * 8);
3641 a = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
3642 M_ALD(REG_ITMP3, REG_PV, a);
3643 M_JSR(REG_RA, REG_ITMP3);
3645 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3647 if (m->isleafmethod)
3648 M_ALD(REG_RA, REG_SP, 1 * 8);
3650 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3651 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3653 a = dseg_addaddress(cd, asm_handle_exception);
3654 M_ALD(REG_ITMP3, REG_PV, a);
3660 /* generate ArrayIndexOutOfBoundsException stubs */
3664 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3665 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3667 (u1 *) mcodeptr - cd->mcodebase);
3671 /* move index register into REG_ITMP1 */
3673 M_MOV(bref->reg, REG_ITMP1);
3674 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3676 if (xcodeptr != NULL) {
3677 M_BR(xcodeptr - mcodeptr);
3681 xcodeptr = mcodeptr;
3683 M_MOV(REG_PV, rd->argintregs[0]);
3684 M_MOV(REG_SP, rd->argintregs[1]);
3686 if (m->isleafmethod)
3687 M_MOV(REG_RA, rd->argintregs[2]);
3689 M_ALD(rd->argintregs[2],
3690 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3692 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3693 M_MOV(REG_ITMP1, rd->argintregs[4]);
3695 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3696 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3698 if (m->isleafmethod)
3699 M_AST(REG_RA, REG_SP, 1 * 8);
3701 a = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
3702 M_ALD(REG_ITMP3, REG_PV, a);
3703 M_JSR(REG_RA, REG_ITMP3);
3705 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3707 if (m->isleafmethod)
3708 M_ALD(REG_RA, REG_SP, 1 * 8);
3710 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3711 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3713 a = dseg_addaddress(cd, asm_handle_exception);
3714 M_ALD(REG_ITMP3, REG_PV, a);
3720 /* generate ArrayStoreException stubs */
3724 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
3725 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3727 (u1 *) mcodeptr - cd->mcodebase);
3731 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3733 if (xcodeptr != NULL) {
3734 M_BR(xcodeptr - mcodeptr);
3738 xcodeptr = mcodeptr;
3740 M_MOV(REG_PV, rd->argintregs[0]);
3741 M_MOV(REG_SP, rd->argintregs[1]);
3742 M_ALD(rd->argintregs[2],
3743 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3744 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3746 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3747 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3749 a = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
3750 M_ALD(REG_ITMP3, REG_PV, a);
3751 M_JSR(REG_RA, REG_ITMP3);
3753 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3755 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3756 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3758 a = dseg_addaddress(cd, asm_handle_exception);
3759 M_ALD(REG_ITMP3, REG_PV, a);
3765 /* generate ClassCastException stubs */
3769 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3770 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3772 (u1 *) mcodeptr - cd->mcodebase);
3776 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3778 if (xcodeptr != NULL) {
3779 M_BR(xcodeptr - mcodeptr);
3783 xcodeptr = mcodeptr;
3785 M_MOV(REG_PV, rd->argintregs[0]);
3786 M_MOV(REG_SP, rd->argintregs[1]);
3788 if (m->isleafmethod)
3789 M_MOV(REG_RA, rd->argintregs[2]);
3791 M_ALD(rd->argintregs[2],
3792 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3794 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3796 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3797 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3799 if (m->isleafmethod)
3800 M_AST(REG_RA, REG_SP, 1 * 8);
3802 a = dseg_addaddress(cd, stacktrace_inline_classcastexception);
3803 M_ALD(REG_ITMP3, REG_PV, a);
3804 M_JSR(REG_RA, REG_ITMP3);
3806 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3808 if (m->isleafmethod)
3809 M_ALD(REG_RA, REG_SP, 1 * 8);
3811 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3812 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3814 a = dseg_addaddress(cd, asm_handle_exception);
3815 M_ALD(REG_ITMP3, REG_PV, a);
3821 /* generate NullPointerException stubs */
3825 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3826 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3828 (u1 *) mcodeptr - cd->mcodebase);
3832 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3834 if (xcodeptr != NULL) {
3835 M_BR(xcodeptr - mcodeptr);
3839 xcodeptr = mcodeptr;
3841 M_MOV(REG_PV, rd->argintregs[0]);
3842 M_MOV(REG_SP, rd->argintregs[1]);
3844 if (m->isleafmethod)
3845 M_MOV(REG_RA, rd->argintregs[2]);
3847 M_ALD(rd->argintregs[2],
3848 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3850 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3852 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3853 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3855 if (m->isleafmethod)
3856 M_AST(REG_RA, REG_SP, 1 * 8);
3858 a = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
3859 M_ALD(REG_ITMP3, REG_PV, a);
3860 M_JSR(REG_RA, REG_ITMP3);
3862 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3864 if (m->isleafmethod)
3865 M_ALD(REG_RA, REG_SP, 1 * 8);
3867 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3868 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3870 a = dseg_addaddress(cd, asm_handle_exception);
3871 M_ALD(REG_ITMP3, REG_PV, a);
3877 /* generate exception check stubs */
3881 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3882 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3884 (u1 *) mcodeptr - cd->mcodebase);
3888 if (xcodeptr != NULL) {
3889 M_BR(xcodeptr - mcodeptr);
3890 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3893 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3895 xcodeptr = mcodeptr;
3897 M_MOV(REG_PV, rd->argintregs[0]);
3898 M_MOV(REG_SP, rd->argintregs[1]);
3899 M_ALD(rd->argintregs[2],
3900 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3901 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3903 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3904 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3906 a = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
3907 M_ALD(REG_ITMP3, REG_PV, a);
3908 M_JSR(REG_RA, REG_ITMP3);
3910 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3912 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3913 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3915 a = dseg_addaddress(cd, asm_handle_exception);
3916 M_ALD(REG_ITMP3, REG_PV, a);
3922 /* generate patcher stub call code */
3929 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3930 /* check code segment size */
3934 /* Get machine code which is patched back in later. The call is */
3935 /* 2 instruction words long. */
3937 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3939 /* We need to split this, because an unaligned 8 byte read causes */
3942 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3944 /* patch in the call to call the following code (done at compile */
3947 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3948 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3950 disp = (s4) (tmpmcodeptr - (xcodeptr + 1));
3952 if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) {
3954 new_internalerror("Jump offset is out of range: %d > +/-%d",
3962 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3964 /* create stack frame */
3966 M_ASUB_IMM(REG_SP, 6 * 8, REG_SP);
3968 /* calculate return address and move it onto the stack */
3970 M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
3971 M_AST(REG_ITMP3, REG_SP, 5 * 8);
3973 /* move pointer to java_objectheader onto stack */
3975 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3976 /* create a virtual java_objectheader */
3978 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3979 disp = dseg_addaddress(cd, NULL); /* vftbl */
3981 M_LDA(REG_ITMP3, REG_PV, disp);
3982 M_AST(REG_ITMP3, REG_SP, 4 * 8);
3987 /* move machine code onto stack */
3989 disp = dseg_adds8(cd, mcode);
3990 M_LLD(REG_ITMP3, REG_PV, disp);
3991 M_LST(REG_ITMP3, REG_SP, 3 * 8);
3993 /* move class/method/field reference onto stack */
3995 disp = dseg_addaddress(cd, pref->ref);
3996 M_ALD(REG_ITMP3, REG_PV, disp);
3997 M_AST(REG_ITMP3, REG_SP, 2 * 8);
3999 /* move data segment displacement onto stack */
4001 disp = dseg_adds4(cd, pref->disp);
4002 M_ILD(REG_ITMP3, REG_PV, disp);
4003 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4005 /* move patcher function pointer onto stack */
4007 disp = dseg_addaddress(cd, pref->patcher);
4008 M_ALD(REG_ITMP3, REG_PV, disp);
4009 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4011 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4012 M_ALD(REG_ITMP3, REG_PV, disp);
4019 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4021 docacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4023 /* everything's ok */
4029 /* createcompilerstub **********************************************************
4031 Creates a stub routine which calls the compiler.
4033 *******************************************************************************/
4035 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
4036 #define COMPILERSTUB_CODESIZE 4 * 4
4038 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4041 u1 *createcompilerstub(methodinfo *m)
4043 u1 *s; /* memory to hold the stub */
4045 s4 *mcodeptr; /* code generation pointer */
4047 s = CNEW(u1, COMPILERSTUB_SIZE);
4049 /* set data pointer and code pointer */
4052 s = s + COMPILERSTUB_DATASIZE;
4054 mcodeptr = (s4 *) s;
4056 /* Store the methodinfo* in the same place as in the methodheader
4057 for compiled methods. */
4059 d[0] = (ptrint) asm_call_jit_compiler;
4062 M_ALD_INTERN(REG_ITMP1, REG_PV, -1 * SIZEOF_VOID_P); /* method pointer */
4063 M_ALD_INTERN(REG_PV, REG_PV, -2 * SIZEOF_VOID_P); /* pointer to compiler */
4067 (void) docacheflush((void *) s, (char *) mcodeptr - (char *) s);
4069 #if defined(ENABLE_STATISTICS)
4071 count_cstub_len += COMPILERSTUB_SIZE;
4078 /* createnativestub ************************************************************
4080 Creates a stub routine which calls a native method.
4082 *******************************************************************************/
4084 u1 *createnativestub(functionptr f, methodinfo *m, codegendata *cd,
4085 registerdata *rd, methoddesc *nmd)
4087 s4 *mcodeptr; /* code generation pointer */
4088 s4 stackframesize; /* size of stackframe if needed */
4091 s4 i, j; /* count variables */
4094 s4 funcdisp; /* displacement of the function */
4097 /* initialize variables */
4100 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4103 /* calculate stack frame size */
4106 1 + /* return address */
4107 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4108 sizeof(localref_table) / SIZEOF_VOID_P +
4109 md->paramcount + /* for saving arguments over calls */
4110 1 + /* for saving return address */
4114 /* create method header */
4116 #if SIZEOF_VOID_P == 4
4117 (void) dseg_addaddress(cd, m); /* MethodPointer */
4119 (void) dseg_addaddress(cd, m); /* MethodPointer */
4120 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4121 (void) dseg_adds4(cd, 0); /* IsSync */
4122 (void) dseg_adds4(cd, 0); /* IsLeaf */
4123 (void) dseg_adds4(cd, 0); /* IntSave */
4124 (void) dseg_adds4(cd, 0); /* FltSave */
4125 (void) dseg_addlinenumbertablesize(cd);
4126 (void) dseg_adds4(cd, 0); /* ExTableSize */
4129 /* initialize mcode variables */
4131 mcodeptr = (s4 *) cd->mcodeptr;
4134 /* generate stub code */
4136 M_LDA(REG_SP, REG_SP, -stackframesize * 8); /* build up stackframe */
4137 M_AST(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* store ra */
4140 /* call trace function */
4143 M_LDA(REG_SP, REG_SP, -(1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4145 /* save integer argument registers */
4147 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4148 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4149 M_LST(rd->argintregs[i], REG_SP, (1 + i) * 8);
4151 /* save and copy float arguments into integer registers */
4153 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4154 t = md->paramtypes[i].type;
4156 if (IS_FLT_DBL_TYPE(t)) {
4157 if (IS_2_WORD_TYPE(t)) {
4158 M_DST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4159 M_LLD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4161 M_FST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4162 M_ILD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4167 disp = dseg_addaddress(cd, m);
4168 M_ALD(REG_ITMP1, REG_PV, disp);
4169 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4170 disp = dseg_addaddress(cd, builtin_trace_args);
4171 M_ALD(REG_ITMP3, REG_PV, disp);
4172 M_JSR(REG_RA, REG_ITMP3);
4175 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4176 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4177 M_LLD(rd->argintregs[i], REG_SP, (1 + i) * 8);
4179 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4180 t = md->paramtypes[i].type;
4182 if (IS_FLT_DBL_TYPE(t)) {
4183 if (IS_2_WORD_TYPE(t)) {
4184 M_DLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4186 M_FLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4191 M_LDA(REG_SP, REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4195 /* get function address (this must happen before the stackframeinfo) */
4197 funcdisp = dseg_addaddress(cd, f);
4199 #if !defined(ENABLE_STATICVM)
4201 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m, funcdisp);
4203 if (opt_showdisassemble) {
4209 /* save integer and float argument registers */
4211 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4212 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4213 M_LST(rd->argintregs[i], REG_SP, j * 8);
4218 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4219 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4220 M_DST(rd->argfltregs[i], REG_SP, j * 8);
4225 /* prepare data structures for native function call */
4227 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4228 M_MOV(REG_PV, rd->argintregs[1]);
4229 M_AADD_IMM(REG_SP, stackframesize * 8, rd->argintregs[2]);
4230 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8 - SIZEOF_VOID_P);
4231 disp = dseg_addaddress(cd, codegen_start_native_call);
4232 M_ALD(REG_ITMP3, REG_PV, disp);
4233 M_JSR(REG_RA, REG_ITMP3);
4234 M_NOP; /* XXX fill me! */
4236 /* restore integer and float argument registers */
4238 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4239 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4240 M_LLD(rd->argintregs[i], REG_SP, j * 8);
4245 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4246 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4247 M_DLD(rd->argfltregs[i], REG_SP, j * 8);
4252 /* copy or spill arguments to new locations */
4254 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4255 t = md->paramtypes[i].type;
4257 if (IS_INT_LNG_TYPE(t)) {
4258 if (!md->params[i].inmemory) {
4259 s1 = rd->argintregs[md->params[i].regoff];
4261 if (!nmd->params[j].inmemory) {
4262 s2 = rd->argintregs[nmd->params[j].regoff];
4265 s2 = nmd->params[j].regoff;
4266 M_AST(s1, REG_SP, s2 * 8);
4270 s1 = md->params[i].regoff + stackframesize;
4271 s2 = nmd->params[j].regoff;
4272 M_ALD(REG_ITMP1, REG_SP, s1 * 8);
4273 M_AST(REG_ITMP1, REG_SP, s2 * 8);
4277 if (!md->params[i].inmemory) {
4278 s1 = rd->argfltregs[md->params[i].regoff];
4280 if (!nmd->params[j].inmemory) {
4281 s2 = rd->argfltregs[nmd->params[j].regoff];
4282 M_TFLTMOVE(t, s1, s2);
4284 s2 = nmd->params[j].regoff;
4285 if (IS_2_WORD_TYPE(t))
4286 M_DST(s1, REG_SP, s2 * 8);
4288 M_FST(s1, REG_SP, s2 * 8);
4292 s1 = md->params[i].regoff + stackframesize;
4293 s2 = nmd->params[j].regoff;
4294 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4295 if (IS_2_WORD_TYPE(t))
4296 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4298 M_FST(REG_FTMP1, REG_SP, s2 * 8);
4303 /* put class into second argument register */
4305 if (m->flags & ACC_STATIC) {
4306 disp = dseg_addaddress(cd, m->class);
4307 M_ALD(rd->argintregs[1], REG_PV, disp);
4310 /* put env into first argument register */
4312 disp = dseg_addaddress(cd, &env);
4313 M_ALD(rd->argintregs[0], REG_PV, disp);
4315 /* do the native function call */
4317 M_ALD(REG_ITMP3, REG_PV, funcdisp); /* load adress of native method */
4318 M_JSR(REG_RA, REG_ITMP3); /* call native method */
4319 M_NOP; /* delay slot */
4321 /* save return value */
4323 if (IS_INT_LNG_TYPE(md->returntype.type))
4324 M_LST(REG_RESULT, REG_SP, 0 * 8);
4326 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4328 /* remove native stackframe info */
4330 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4331 disp = dseg_addaddress(cd, codegen_finish_native_call);
4332 M_ALD(REG_ITMP3, REG_PV, disp);
4333 M_JSR(REG_RA, REG_ITMP3);
4334 M_NOP; /* XXX fill me! */
4336 /* call finished trace function */
4339 if (IS_INT_LNG_TYPE(md->returntype.type))
4340 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4342 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4344 disp = dseg_addaddress(cd, m);
4345 M_ALD(rd->argintregs[0], REG_PV, disp);
4347 M_MOV(REG_RESULT, rd->argintregs[1]);
4348 M_DMFC1(REG_ITMP1, REG_FRESULT);
4349 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4350 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4352 disp = dseg_addaddress(cd, builtin_displaymethodstop);
4353 M_ALD(REG_ITMP3, REG_PV, disp);
4354 M_JSR(REG_RA, REG_ITMP3);
4358 /* check for exception */
4360 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4361 disp = dseg_addaddress(cd, builtin_get_exceptionptrptr);
4362 M_ALD(REG_ITMP3, REG_PV, disp);
4363 M_JSR(REG_RA, REG_ITMP3);
4365 M_MOV(REG_RESULT, REG_ITMP3);
4367 disp = dseg_addaddress(cd, &_exceptionptr);
4368 M_ALD(REG_ITMP3, REG_PV, disp); /* get address of exceptionptr */
4370 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4372 M_ALD(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* load ra */
4374 /* restore return value */
4376 if (IS_INT_LNG_TYPE(md->returntype.type))
4377 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4379 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4381 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
4382 M_LDA(REG_SP, REG_SP, stackframesize * 8);/* remove stackframe, DELAY SLOT*/
4384 M_RET(REG_RA); /* return to caller */
4385 M_NOP; /* DELAY SLOT */
4387 /* handle exception */
4389 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4391 disp = dseg_addaddress(cd, asm_handle_nat_exception);
4392 M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */
4393 M_JMP(REG_ITMP3); /* jump to asm exception handler */
4394 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4397 /* generate static stub call code */
4405 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4406 /* Get machine code which is patched back in later. The call is */
4407 /* 2 instruction words long. */
4409 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4411 /* We need to split this, because an unaligned 8 byte read causes */
4414 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
4416 /* patch in the call to call the following code (done at compile */
4419 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4420 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4422 M_BRS(tmpmcodeptr - (xcodeptr + 1));
4423 M_NOP; /* branch delay slot */
4425 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4427 /* create stack frame */
4429 M_LSUB_IMM(REG_SP, 6 * 8, REG_SP);
4431 /* move return address onto stack */
4433 M_AST(REG_RA, REG_SP, 5 * 8);
4435 /* move pointer to java_objectheader onto stack */
4437 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4438 /* order reversed because of data segment layout */
4440 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4441 disp = dseg_addaddress(cd, NULL); /* vftbl */
4443 M_LDA(REG_ITMP3, REG_PV, disp);
4444 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4446 M_AST(REG_ZERO, REG_SP, 4 * 8);
4449 /* move machine code onto stack */
4451 disp = dseg_adds8(cd, mcode);
4452 M_LLD(REG_ITMP3, REG_PV, disp);
4453 M_LST(REG_ITMP3, REG_SP, 3 * 8);
4455 /* move class/method/field reference onto stack */
4457 disp = dseg_addaddress(cd, pref->ref);
4458 M_ALD(REG_ITMP3, REG_PV, disp);
4459 M_AST(REG_ITMP3, REG_SP, 2 * 8);
4461 /* move data segment displacement onto stack */
4463 disp = dseg_adds4(cd, pref->disp);
4464 M_ILD(REG_ITMP3, REG_PV, disp);
4465 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4467 /* move patcher function pointer onto stack */
4469 disp = dseg_addaddress(cd, pref->patcher);
4470 M_ALD(REG_ITMP3, REG_PV, disp);
4471 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4473 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4474 M_ALD(REG_ITMP3, REG_PV, disp);
4480 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4482 docacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4484 return m->entrypoint;
4489 * These are local overrides for various environment variables in Emacs.
4490 * Please do not remove this and leave it at the end of the file, where
4491 * Emacs will automagically detect them.
4492 * ---------------------------------------------------------------------
4495 * indent-tabs-mode: t