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 4640 2006-03-16 17:24:18Z twisti $
53 #include "vm/jit/mips/arch.h"
54 #include "vm/jit/mips/codegen.h"
56 #include "native/native.h"
57 #include "vm/builtin.h"
59 #include "vm/exceptions.h"
60 #include "vm/options.h"
61 #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 */
239 if (opt_verbosecall) {
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_add_nullpointerexception_ref(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 */
270 if (opt_verbosecall) {
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 */
285 if (opt_verbosecall) {
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_add_nullpointerexception_ref(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_add_arraystoreexception_ref(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 */
2746 if (opt_verbosecall) {
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_add_fillinstacktrace_ref(cd, mcodeptr);
3016 case ICMD_INVOKESPECIAL:
3017 M_BEQZ(rd->argintregs[0], 0);
3018 codegen_add_nullpointerexception_ref(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_add_classcastexception_ref(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_add_classcastexception_ref(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_add_classcastexception_ref(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_add_classcastexception_ref(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_add_fillinstacktrace_ref(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);
3605 /* generate ArithmeticException stubs */
3609 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3610 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3612 (u1 *) mcodeptr - cd->mcodebase);
3616 if (xcodeptr != NULL) {
3617 M_BR(xcodeptr - mcodeptr);
3618 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3621 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3623 xcodeptr = mcodeptr;
3625 M_MOV(REG_PV, rd->argintregs[0]);
3626 M_MOV(REG_SP, rd->argintregs[1]);
3628 if (m->isleafmethod)
3629 M_MOV(REG_RA, rd->argintregs[2]);
3631 M_ALD(rd->argintregs[2],
3632 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3634 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3636 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3637 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3639 if (m->isleafmethod)
3640 M_AST(REG_RA, REG_SP, 1 * 8);
3642 a = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
3643 M_ALD(REG_ITMP3, REG_PV, a);
3644 M_JSR(REG_RA, REG_ITMP3);
3646 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3648 if (m->isleafmethod)
3649 M_ALD(REG_RA, REG_SP, 1 * 8);
3651 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3652 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3654 a = dseg_addaddress(cd, asm_handle_exception);
3655 M_ALD(REG_ITMP3, REG_PV, a);
3661 /* generate ArrayIndexOutOfBoundsException stubs */
3665 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3666 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3668 (u1 *) mcodeptr - cd->mcodebase);
3672 /* move index register into REG_ITMP1 */
3674 M_MOV(bref->reg, REG_ITMP1);
3675 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3677 if (xcodeptr != NULL) {
3678 M_BR(xcodeptr - mcodeptr);
3682 xcodeptr = mcodeptr;
3684 M_MOV(REG_PV, rd->argintregs[0]);
3685 M_MOV(REG_SP, rd->argintregs[1]);
3687 if (m->isleafmethod)
3688 M_MOV(REG_RA, rd->argintregs[2]);
3690 M_ALD(rd->argintregs[2],
3691 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3693 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3694 M_MOV(REG_ITMP1, rd->argintregs[4]);
3696 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3697 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3699 if (m->isleafmethod)
3700 M_AST(REG_RA, REG_SP, 1 * 8);
3702 a = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
3703 M_ALD(REG_ITMP3, REG_PV, a);
3704 M_JSR(REG_RA, REG_ITMP3);
3706 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3708 if (m->isleafmethod)
3709 M_ALD(REG_RA, REG_SP, 1 * 8);
3711 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3712 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3714 a = dseg_addaddress(cd, asm_handle_exception);
3715 M_ALD(REG_ITMP3, REG_PV, a);
3721 /* generate ArrayStoreException stubs */
3725 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
3726 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3728 (u1 *) mcodeptr - cd->mcodebase);
3732 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3734 if (xcodeptr != NULL) {
3735 M_BR(xcodeptr - mcodeptr);
3739 xcodeptr = mcodeptr;
3741 M_MOV(REG_PV, rd->argintregs[0]);
3742 M_MOV(REG_SP, rd->argintregs[1]);
3743 M_ALD(rd->argintregs[2],
3744 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3745 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3747 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3748 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3750 a = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
3751 M_ALD(REG_ITMP3, REG_PV, a);
3752 M_JSR(REG_RA, REG_ITMP3);
3754 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3756 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3757 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3759 a = dseg_addaddress(cd, asm_handle_exception);
3760 M_ALD(REG_ITMP3, REG_PV, a);
3766 /* generate ClassCastException stubs */
3770 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3771 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3773 (u1 *) mcodeptr - cd->mcodebase);
3777 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3779 if (xcodeptr != NULL) {
3780 M_BR(xcodeptr - mcodeptr);
3784 xcodeptr = mcodeptr;
3786 M_MOV(REG_PV, rd->argintregs[0]);
3787 M_MOV(REG_SP, rd->argintregs[1]);
3789 if (m->isleafmethod)
3790 M_MOV(REG_RA, rd->argintregs[2]);
3792 M_ALD(rd->argintregs[2],
3793 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3795 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3797 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3798 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3800 if (m->isleafmethod)
3801 M_AST(REG_RA, REG_SP, 1 * 8);
3803 a = dseg_addaddress(cd, stacktrace_inline_classcastexception);
3804 M_ALD(REG_ITMP3, REG_PV, a);
3805 M_JSR(REG_RA, REG_ITMP3);
3807 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3809 if (m->isleafmethod)
3810 M_ALD(REG_RA, REG_SP, 1 * 8);
3812 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3813 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3815 a = dseg_addaddress(cd, asm_handle_exception);
3816 M_ALD(REG_ITMP3, REG_PV, a);
3822 /* generate NullPointerException stubs */
3826 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3827 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3829 (u1 *) mcodeptr - cd->mcodebase);
3833 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3835 if (xcodeptr != NULL) {
3836 M_BR(xcodeptr - mcodeptr);
3840 xcodeptr = mcodeptr;
3842 M_MOV(REG_PV, rd->argintregs[0]);
3843 M_MOV(REG_SP, rd->argintregs[1]);
3845 if (m->isleafmethod)
3846 M_MOV(REG_RA, rd->argintregs[2]);
3848 M_ALD(rd->argintregs[2],
3849 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3851 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3853 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3854 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3856 if (m->isleafmethod)
3857 M_AST(REG_RA, REG_SP, 1 * 8);
3859 a = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
3860 M_ALD(REG_ITMP3, REG_PV, a);
3861 M_JSR(REG_RA, REG_ITMP3);
3863 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3865 if (m->isleafmethod)
3866 M_ALD(REG_RA, REG_SP, 1 * 8);
3868 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3869 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3871 a = dseg_addaddress(cd, asm_handle_exception);
3872 M_ALD(REG_ITMP3, REG_PV, a);
3878 /* generate exception check stubs */
3882 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3883 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3885 (u1 *) mcodeptr - cd->mcodebase);
3889 if (xcodeptr != NULL) {
3890 M_BR(xcodeptr - mcodeptr);
3891 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3894 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3896 xcodeptr = mcodeptr;
3898 M_MOV(REG_PV, rd->argintregs[0]);
3899 M_MOV(REG_SP, rd->argintregs[1]);
3900 M_ALD(rd->argintregs[2],
3901 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3902 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3904 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3905 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3907 a = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
3908 M_ALD(REG_ITMP3, REG_PV, a);
3909 M_JSR(REG_RA, REG_ITMP3);
3911 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3913 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3914 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3916 a = dseg_addaddress(cd, asm_handle_exception);
3917 M_ALD(REG_ITMP3, REG_PV, a);
3925 /* generate exception and patcher stubs */
3934 savedmcodeptr = NULL;
3936 /* generate exception stubs */
3938 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
3939 gen_resolvebranch((u1 *) cd->mcodebase + eref->branchpos,
3941 (u1 *) mcodeptr - cd->mcodebase);
3945 /* Check if the exception is an
3946 ArrayIndexOutOfBoundsException. If so, move index register
3949 if (eref->reg != -1)
3950 M_MOV(eref->reg, REG_ITMP1);
3952 /* calcuate exception address */
3954 M_LDA(REG_ITMP2_XPC, REG_PV, eref->branchpos - 4);
3956 /* move function to call into REG_ITMP3 */
3958 disp = dseg_addaddress(cd, eref->function);
3959 M_ALD(REG_ITMP3, REG_PV, disp);
3961 if (savedmcodeptr != NULL) {
3962 M_BR(savedmcodeptr - mcodeptr);
3966 savedmcodeptr = mcodeptr;
3968 M_MOV(REG_PV, rd->argintregs[0]);
3969 M_MOV(REG_SP, rd->argintregs[1]);
3971 if (m->isleafmethod)
3972 M_MOV(REG_RA, rd->argintregs[2]);
3974 M_ALD(rd->argintregs[2],
3975 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3977 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3978 M_MOV(REG_ITMP1, rd->argintregs[4]);
3980 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3981 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3983 if (m->isleafmethod)
3984 M_AST(REG_RA, REG_SP, 1 * 8);
3986 M_JSR(REG_RA, REG_ITMP3);
3988 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3990 if (m->isleafmethod)
3991 M_ALD(REG_RA, REG_SP, 1 * 8);
3993 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3994 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3996 a = dseg_addaddress(cd, asm_handle_exception);
3997 M_ALD(REG_ITMP3, REG_PV, a);
4004 /* generate code patching stub call code */
4006 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4007 /* check code segment size */
4011 /* Get machine code which is patched back in later. The
4012 call is 2 instruction words long. */
4014 tmpmcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4016 /* We need to split this, because an unaligned 8 byte read
4017 causes a SIGSEGV. */
4019 mcode = ((u8) tmpmcodeptr[1] << 32) + (u4) tmpmcodeptr[0];
4021 /* Patch in the call to call the following code (done at
4024 savedmcodeptr = mcodeptr; /* save current mcodeptr */
4025 mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
4027 disp = (s4) (savedmcodeptr - (tmpmcodeptr + 1));
4029 if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) {
4031 new_internalerror("Jump offset is out of range: %d > +/-%d",
4039 mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
4041 /* create stack frame */
4043 M_ASUB_IMM(REG_SP, 6 * 8, REG_SP);
4045 /* calculate return address and move it onto the stack */
4047 M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
4048 M_AST(REG_ITMP3, REG_SP, 5 * 8);
4050 /* move pointer to java_objectheader onto stack */
4052 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4053 /* create a virtual java_objectheader */
4055 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4056 disp = dseg_addaddress(cd, NULL); /* vftbl */
4058 M_LDA(REG_ITMP3, REG_PV, disp);
4059 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4064 /* move machine code onto stack */
4066 disp = dseg_adds8(cd, mcode);
4067 M_LLD(REG_ITMP3, REG_PV, disp);
4068 M_LST(REG_ITMP3, REG_SP, 3 * 8);
4070 /* move class/method/field reference onto stack */
4072 disp = dseg_addaddress(cd, pref->ref);
4073 M_ALD(REG_ITMP3, REG_PV, disp);
4074 M_AST(REG_ITMP3, REG_SP, 2 * 8);
4076 /* move data segment displacement onto stack */
4078 disp = dseg_adds4(cd, pref->disp);
4079 M_ILD(REG_ITMP3, REG_PV, disp);
4080 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4082 /* move patcher function pointer onto stack */
4084 disp = dseg_addaddress(cd, pref->patcher);
4085 M_ALD(REG_ITMP3, REG_PV, disp);
4086 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4088 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4089 M_ALD(REG_ITMP3, REG_PV, disp);
4095 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4097 docacheflush((void *) cd->code->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4099 /* everything's ok */
4105 /* createcompilerstub **********************************************************
4107 Creates a stub routine which calls the compiler.
4109 *******************************************************************************/
4111 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
4112 #define COMPILERSTUB_CODESIZE 4 * 4
4114 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4117 u1 *createcompilerstub(methodinfo *m)
4119 u1 *s; /* memory to hold the stub */
4121 s4 *mcodeptr; /* code generation pointer */
4123 s = CNEW(u1, COMPILERSTUB_SIZE);
4125 /* set data pointer and code pointer */
4128 s = s + COMPILERSTUB_DATASIZE;
4130 mcodeptr = (s4 *) s;
4132 /* Store the methodinfo* in the same place as in the methodheader
4133 for compiled methods. */
4135 d[0] = (ptrint) asm_call_jit_compiler;
4138 M_ALD_INTERN(REG_ITMP1, REG_PV, -1 * SIZEOF_VOID_P); /* method pointer */
4139 M_ALD_INTERN(REG_PV, REG_PV, -2 * SIZEOF_VOID_P); /* pointer to compiler */
4143 (void) docacheflush((void *) s, (char *) mcodeptr - (char *) s);
4145 #if defined(ENABLE_STATISTICS)
4147 count_cstub_len += COMPILERSTUB_SIZE;
4154 /* createnativestub ************************************************************
4156 Creates a stub routine which calls a native method.
4158 *******************************************************************************/
4160 u1 *createnativestub(functionptr f, methodinfo *m, codegendata *cd,
4161 registerdata *rd, methoddesc *nmd)
4163 s4 *mcodeptr; /* code generation pointer */
4164 s4 stackframesize; /* size of stackframe if needed */
4167 s4 i, j; /* count variables */
4170 s4 funcdisp; /* displacement of the function */
4173 /* initialize variables */
4176 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4179 /* calculate stack frame size */
4182 1 + /* return address */
4183 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4184 sizeof(localref_table) / SIZEOF_VOID_P +
4185 md->paramcount + /* for saving arguments over calls */
4186 1 + /* for saving return address */
4190 /* create method header */
4192 #if SIZEOF_VOID_P == 4
4193 (void) dseg_addaddress(cd, m); /* MethodPointer */
4195 (void) dseg_addaddress(cd, m); /* MethodPointer */
4196 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4197 (void) dseg_adds4(cd, 0); /* IsSync */
4198 (void) dseg_adds4(cd, 0); /* IsLeaf */
4199 (void) dseg_adds4(cd, 0); /* IntSave */
4200 (void) dseg_adds4(cd, 0); /* FltSave */
4201 (void) dseg_addlinenumbertablesize(cd);
4202 (void) dseg_adds4(cd, 0); /* ExTableSize */
4205 /* initialize mcode variables */
4207 mcodeptr = (s4 *) cd->mcodeptr;
4210 /* generate stub code */
4212 M_LDA(REG_SP, REG_SP, -stackframesize * 8); /* build up stackframe */
4213 M_AST(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* store ra */
4216 /* call trace function */
4218 if (opt_verbosecall) {
4219 M_LDA(REG_SP, REG_SP, -(1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4221 /* save integer argument registers */
4223 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4224 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4225 M_LST(rd->argintregs[i], REG_SP, (1 + i) * 8);
4227 /* save and copy float arguments into integer registers */
4229 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4230 t = md->paramtypes[i].type;
4232 if (IS_FLT_DBL_TYPE(t)) {
4233 if (IS_2_WORD_TYPE(t)) {
4234 M_DST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4235 M_LLD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4237 M_FST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4238 M_ILD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4243 disp = dseg_addaddress(cd, m);
4244 M_ALD(REG_ITMP1, REG_PV, disp);
4245 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4246 disp = dseg_addaddress(cd, builtin_trace_args);
4247 M_ALD(REG_ITMP3, REG_PV, disp);
4248 M_JSR(REG_RA, REG_ITMP3);
4251 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4252 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4253 M_LLD(rd->argintregs[i], REG_SP, (1 + i) * 8);
4255 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4256 t = md->paramtypes[i].type;
4258 if (IS_FLT_DBL_TYPE(t)) {
4259 if (IS_2_WORD_TYPE(t)) {
4260 M_DLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4262 M_FLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4267 M_LDA(REG_SP, REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4271 /* get function address (this must happen before the stackframeinfo) */
4273 funcdisp = dseg_addaddress(cd, f);
4275 #if !defined(WITH_STATIC_CLASSPATH)
4277 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m, funcdisp);
4279 if (opt_showdisassemble) {
4285 /* save integer and float argument registers */
4287 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4288 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4289 M_LST(rd->argintregs[i], REG_SP, j * 8);
4294 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4295 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4296 M_DST(rd->argfltregs[i], REG_SP, j * 8);
4301 /* prepare data structures for native function call */
4303 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4304 M_MOV(REG_PV, rd->argintregs[1]);
4305 M_AADD_IMM(REG_SP, stackframesize * 8, rd->argintregs[2]);
4306 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8 - SIZEOF_VOID_P);
4307 disp = dseg_addaddress(cd, codegen_start_native_call);
4308 M_ALD(REG_ITMP3, REG_PV, disp);
4309 M_JSR(REG_RA, REG_ITMP3);
4310 M_NOP; /* XXX fill me! */
4312 /* restore integer and float argument registers */
4314 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4315 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4316 M_LLD(rd->argintregs[i], REG_SP, j * 8);
4321 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4322 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4323 M_DLD(rd->argfltregs[i], REG_SP, j * 8);
4328 /* copy or spill arguments to new locations */
4330 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4331 t = md->paramtypes[i].type;
4333 if (IS_INT_LNG_TYPE(t)) {
4334 if (!md->params[i].inmemory) {
4335 s1 = rd->argintregs[md->params[i].regoff];
4337 if (!nmd->params[j].inmemory) {
4338 s2 = rd->argintregs[nmd->params[j].regoff];
4341 s2 = nmd->params[j].regoff;
4342 M_AST(s1, REG_SP, s2 * 8);
4346 s1 = md->params[i].regoff + stackframesize;
4347 s2 = nmd->params[j].regoff;
4348 M_ALD(REG_ITMP1, REG_SP, s1 * 8);
4349 M_AST(REG_ITMP1, REG_SP, s2 * 8);
4353 if (!md->params[i].inmemory) {
4354 s1 = rd->argfltregs[md->params[i].regoff];
4356 if (!nmd->params[j].inmemory) {
4357 s2 = rd->argfltregs[nmd->params[j].regoff];
4358 M_TFLTMOVE(t, s1, s2);
4360 s2 = nmd->params[j].regoff;
4361 if (IS_2_WORD_TYPE(t))
4362 M_DST(s1, REG_SP, s2 * 8);
4364 M_FST(s1, REG_SP, s2 * 8);
4368 s1 = md->params[i].regoff + stackframesize;
4369 s2 = nmd->params[j].regoff;
4370 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4371 if (IS_2_WORD_TYPE(t))
4372 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4374 M_FST(REG_FTMP1, REG_SP, s2 * 8);
4379 /* put class into second argument register */
4381 if (m->flags & ACC_STATIC) {
4382 disp = dseg_addaddress(cd, m->class);
4383 M_ALD(rd->argintregs[1], REG_PV, disp);
4386 /* put env into first argument register */
4388 disp = dseg_addaddress(cd, _Jv_env);
4389 M_ALD(rd->argintregs[0], REG_PV, disp);
4391 /* do the native function call */
4393 M_ALD(REG_ITMP3, REG_PV, funcdisp); /* load adress of native method */
4394 M_JSR(REG_RA, REG_ITMP3); /* call native method */
4395 M_NOP; /* delay slot */
4397 /* save return value */
4399 if (IS_INT_LNG_TYPE(md->returntype.type))
4400 M_LST(REG_RESULT, REG_SP, 0 * 8);
4402 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4404 /* remove native stackframe info */
4406 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4407 disp = dseg_addaddress(cd, codegen_finish_native_call);
4408 M_ALD(REG_ITMP3, REG_PV, disp);
4409 M_JSR(REG_RA, REG_ITMP3);
4410 M_NOP; /* XXX fill me! */
4412 /* call finished trace function */
4414 if (opt_verbosecall) {
4415 if (IS_INT_LNG_TYPE(md->returntype.type))
4416 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4418 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4420 disp = dseg_addaddress(cd, m);
4421 M_ALD(rd->argintregs[0], REG_PV, disp);
4423 M_MOV(REG_RESULT, rd->argintregs[1]);
4424 M_DMFC1(REG_ITMP1, REG_FRESULT);
4425 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4426 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4428 disp = dseg_addaddress(cd, builtin_displaymethodstop);
4429 M_ALD(REG_ITMP3, REG_PV, disp);
4430 M_JSR(REG_RA, REG_ITMP3);
4434 /* check for exception */
4436 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4437 disp = dseg_addaddress(cd, builtin_get_exceptionptrptr);
4438 M_ALD(REG_ITMP3, REG_PV, disp);
4439 M_JSR(REG_RA, REG_ITMP3);
4441 M_MOV(REG_RESULT, REG_ITMP3);
4443 disp = dseg_addaddress(cd, &_exceptionptr);
4444 M_ALD(REG_ITMP3, REG_PV, disp); /* get address of exceptionptr */
4446 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4448 M_ALD(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* load ra */
4450 /* restore return value */
4452 if (IS_INT_LNG_TYPE(md->returntype.type))
4453 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4455 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4457 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
4458 M_LDA(REG_SP, REG_SP, stackframesize * 8);/* remove stackframe, DELAY SLOT*/
4460 M_RET(REG_RA); /* return to caller */
4461 M_NOP; /* DELAY SLOT */
4463 /* handle exception */
4465 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4467 disp = dseg_addaddress(cd, asm_handle_nat_exception);
4468 M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */
4469 M_JMP(REG_ITMP3); /* jump to asm exception handler */
4470 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4473 /* generate static stub call code */
4481 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4482 /* Get machine code which is patched back in later. The
4483 call is 2 instruction words long. */
4485 tmpmcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4487 /* We need to split this, because an unaligned 8 byte read
4488 causes a SIGSEGV. */
4490 mcode = ((u8) tmpmcodeptr[1] << 32) + (u4) tmpmcodeptr[0];
4492 /* Patch in the call to call the following code (done at
4495 savedmcodeptr = mcodeptr; /* save current mcodeptr */
4496 mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
4498 M_BRS(savedmcodeptr - (tmpmcodeptr + 1));
4499 M_NOP; /* branch delay slot */
4501 mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
4503 /* create stack frame */
4505 M_LSUB_IMM(REG_SP, 6 * 8, REG_SP);
4507 /* move return address onto stack */
4509 M_AST(REG_RA, REG_SP, 5 * 8);
4511 /* move pointer to java_objectheader onto stack */
4513 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4514 /* order reversed because of data segment layout */
4516 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4517 disp = dseg_addaddress(cd, NULL); /* vftbl */
4519 M_LDA(REG_ITMP3, REG_PV, disp);
4520 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4522 M_AST(REG_ZERO, REG_SP, 4 * 8);
4525 /* move machine code onto stack */
4527 disp = dseg_adds8(cd, mcode);
4528 M_LLD(REG_ITMP3, REG_PV, disp);
4529 M_LST(REG_ITMP3, REG_SP, 3 * 8);
4531 /* move class/method/field reference onto stack */
4533 disp = dseg_addaddress(cd, pref->ref);
4534 M_ALD(REG_ITMP3, REG_PV, disp);
4535 M_AST(REG_ITMP3, REG_SP, 2 * 8);
4537 /* move data segment displacement onto stack */
4539 disp = dseg_adds4(cd, pref->disp);
4540 M_ILD(REG_ITMP3, REG_PV, disp);
4541 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4543 /* move patcher function pointer onto stack */
4545 disp = dseg_addaddress(cd, pref->patcher);
4546 M_ALD(REG_ITMP3, REG_PV, disp);
4547 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4549 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4550 M_ALD(REG_ITMP3, REG_PV, disp);
4556 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4558 docacheflush((void *) cd->code->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4560 return cd->code->entrypoint;
4565 * These are local overrides for various environment variables in Emacs.
4566 * Please do not remove this and leave it at the end of the file, where
4567 * Emacs will automagically detect them.
4568 * ---------------------------------------------------------------------
4571 * indent-tabs-mode: t
4575 * vim:noexpandtab:sw=4:ts=4: