1 /* src/vm/jit/mips/codegen.c - machine code generator for MIPS
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
30 Changes: Christian Thalinger
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 3879 2005-12-05 19:36:57Z twisti $
53 #include "vm/jit/mips/arch.h"
54 #include "vm/jit/mips/codegen.h"
56 #include "cacao/cacao.h"
57 #include "native/native.h"
58 #include "vm/builtin.h"
60 #include "vm/stringlocal.h"
61 #include "vm/jit/asmpart.h"
62 #include "vm/jit/codegen.inc"
63 #include "vm/jit/jit.h"
66 # include "vm/jit/lsra.h"
67 # include "vm/jit/lsra.inc"
70 #include "vm/jit/patcher.h"
71 #include "vm/jit/reg.h"
72 #include "vm/jit/reg.inc"
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->mcodebase;
159 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
160 MCODECHECK(128 + m->paramcount);
162 /* initialize the last patcher pointer */
164 cd->lastmcodeptr = (u1 *) mcodeptr;
166 /* create stack frame (if necessary) */
169 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
171 /* save return address and used callee saved registers */
174 if (!m->isleafmethod) {
175 p--; M_AST(REG_RA, REG_SP, p * 8);
177 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
178 p--; M_AST(rd->savintregs[i], REG_SP, p * 8);
180 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
181 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
184 /* take arguments out of register or stack frame */
188 for (p = 0, l = 0; p < md->paramcount; p++) {
189 t = md->paramtypes[p].type;
190 var = &(rd->locals[l][t]);
192 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
196 s1 = md->params[p].regoff;
197 if (IS_INT_LNG_TYPE(t)) { /* integer args */
198 if (!md->params[p].inmemory) { /* register arguments */
199 s2 = rd->argintregs[s1];
200 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
201 M_INTMOVE(s2, var->regoff);
202 } else { /* reg arg -> spilled */
203 M_LST(s2, REG_SP, var->regoff * 8);
206 } else { /* stack arguments */
207 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
208 M_LLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
209 } else { /* stack arg -> spilled */
210 var->regoff = parentargs_base + s1;
214 } else { /* floating args */
215 if (!md->params[p].inmemory) { /* register arguments */
216 s2 = rd->argfltregs[s1];
217 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
218 M_TFLTMOVE(var->type, s2, var->regoff);
219 } else { /* reg arg -> spilled */
220 M_DST(s2, REG_SP, var->regoff * 8);
223 } else { /* stack arguments */
224 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
225 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
226 } else { /* stack-arg -> spilled */
227 var->regoff = parentargs_base + s1;
233 /* call monitorenter function */
235 #if defined(USE_THREADS)
236 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
237 /* stack offset for monitor argument */
242 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
244 for (p = 0; p < INT_ARG_CNT; p++)
245 M_LST(rd->argintregs[p], REG_SP, p * 8);
247 for (p = 0; p < FLT_ARG_CNT; p++)
248 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
250 s1 += INT_ARG_CNT + FLT_ARG_CNT;
253 /* decide which monitor enter function to call */
255 if (m->flags & ACC_STATIC) {
256 p = dseg_addaddress(cd, m->class);
257 M_ALD(REG_ITMP1, REG_PV, p);
258 M_AST(REG_ITMP1, REG_SP, s1 * 8);
259 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
260 M_ALD(REG_ITMP3, REG_PV, p);
261 M_JSR(REG_RA, REG_ITMP3);
262 M_INTMOVE(REG_ITMP1, rd->argintregs[0]); /* branch delay */
265 M_BEQZ(rd->argintregs[0], 0);
266 codegen_addxnullrefs(cd, mcodeptr);
267 p = dseg_addaddress(cd, BUILTIN_monitorenter);
268 M_ALD(REG_ITMP3, REG_PV, p);
269 M_JSR(REG_RA, REG_ITMP3);
270 M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* br delay */
274 for (p = 0; p < INT_ARG_CNT; p++)
275 M_LLD(rd->argintregs[p], REG_SP, p * 8);
277 for (p = 0; p < FLT_ARG_CNT; p++)
278 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
281 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
286 /* copy argument registers to stack and call trace function */
289 M_LDA(REG_SP, REG_SP, -(2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
290 M_AST(REG_RA, REG_SP, 1 * 8);
292 /* save integer argument registers */
294 for (p = 0; p < md->paramcount && p < INT_ARG_CNT; p++)
295 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
297 /* save and copy float arguments into integer registers */
299 for (p = 0; p < md->paramcount && p < FLT_ARG_CNT; p++) {
300 t = md->paramtypes[p].type;
302 if (IS_FLT_DBL_TYPE(t)) {
303 if (IS_2_WORD_TYPE(t)) {
304 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
305 M_LLD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
308 M_FST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
309 M_ILD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
313 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
317 /* save temporary registers for leaf methods */
319 if (m->isleafmethod) {
320 for (p = 0; p < INT_TMP_CNT; p++)
321 M_LST(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
323 for (p = 0; p < FLT_TMP_CNT; p++)
324 M_DST(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
327 p = dseg_addaddress(cd, m);
328 M_ALD(REG_ITMP1, REG_PV, p);
329 M_AST(REG_ITMP1, REG_SP, 0 * 8);
330 disp = dseg_addaddress(cd, (void *) builtin_trace_args);
331 M_ALD(REG_ITMP3, REG_PV, disp);
332 M_JSR(REG_RA, REG_ITMP3);
335 M_ALD(REG_RA, REG_SP, 1 * 8);
337 /* restore integer argument registers */
339 for (p = 0; p < md->paramcount && p < INT_ARG_CNT; p++)
340 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
342 /* restore float argument registers */
344 for (p = 0; p < md->paramcount && p < FLT_ARG_CNT; p++) {
345 t = md->paramtypes[p].type;
347 if (IS_FLT_DBL_TYPE(t)) {
348 if (IS_2_WORD_TYPE(t)) {
349 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
352 M_FLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
356 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
360 /* restore temporary registers for leaf methods */
362 if (m->isleafmethod) {
363 for (p = 0; p < INT_TMP_CNT; p++)
364 M_LLD(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
366 for (p = 0; p < FLT_TMP_CNT; p++)
367 M_DLD(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
370 M_LDA(REG_SP, REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
375 /* end of header generation */
377 /* walk through all basic blocks */
379 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
381 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
383 if (bptr->flags >= BBREACHED) {
385 /* branch resolving */
388 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
389 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
395 /* copy interface registers to their destination */
402 while (src != NULL) {
404 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
405 /* d = reg_of_var(m, src, REG_ITMP1); */
406 if (!(src->flags & INMEMORY))
410 M_INTMOVE(REG_ITMP1, d);
411 store_reg_to_var_int(src, d);
417 while (src != NULL) {
419 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
420 d = reg_of_var(rd, src, REG_ITMP1);
421 M_INTMOVE(REG_ITMP1, d);
422 store_reg_to_var_int(src, d);
425 d = reg_of_var(rd, src, REG_IFTMP);
426 if ((src->varkind != STACKVAR)) {
428 if (IS_FLT_DBL_TYPE(s2)) {
429 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
430 s1 = rd->interfaces[len][s2].regoff;
431 M_TFLTMOVE(s2, s1, d);
434 M_DLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
436 store_reg_to_var_flt(src, d);
439 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
440 s1 = rd->interfaces[len][s2].regoff;
444 M_LLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
446 store_reg_to_var_int(src, d);
455 /* walk through all instructions */
461 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
462 if (iptr->line != currentline) {
463 dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
464 currentline = iptr->line;
467 MCODECHECK(64); /* an instruction usually needs < 64 words */
471 case ICMD_NOP: /* ... ==> ... */
474 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
476 var_to_reg_int(s1, src, REG_ITMP1);
478 codegen_addxnullrefs(cd, mcodeptr);
482 /* constant operations ************************************************/
484 case ICMD_ICONST: /* ... ==> ..., constant */
485 /* op1 = 0, val.i = constant */
487 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
488 ICONST(d, iptr->val.i);
489 store_reg_to_var_int(iptr->dst, d);
492 case ICMD_LCONST: /* ... ==> ..., constant */
493 /* op1 = 0, val.l = constant */
495 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
496 LCONST(d, iptr->val.l);
497 store_reg_to_var_int(iptr->dst, d);
500 case ICMD_FCONST: /* ... ==> ..., constant */
501 /* op1 = 0, val.f = constant */
503 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
504 disp = dseg_addfloat(cd, iptr->val.f);
505 M_FLD(d, REG_PV, disp);
506 store_reg_to_var_flt(iptr->dst, d);
509 case ICMD_DCONST: /* ... ==> ..., constant */
510 /* op1 = 0, val.d = constant */
512 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
513 disp = dseg_adddouble(cd, iptr->val.d);
514 M_DLD(d, REG_PV, disp);
515 store_reg_to_var_flt (iptr->dst, d);
518 case ICMD_ACONST: /* ... ==> ..., constant */
519 /* op1 = 0, val.a = constant */
521 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
523 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
524 disp = dseg_addaddress(cd, iptr->val.a);
526 codegen_addpatchref(cd, mcodeptr,
528 (unresolved_class *) iptr->target, disp);
530 if (opt_showdisassemble) {
534 M_ALD(d, REG_PV, disp);
537 if (iptr->val.a == NULL) {
538 M_INTMOVE(REG_ZERO, d);
540 disp = dseg_addaddress(cd, iptr->val.a);
541 M_ALD(d, REG_PV, disp);
544 store_reg_to_var_int(iptr->dst, d);
548 /* load/store operations **********************************************/
550 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
551 case ICMD_LLOAD: /* op1 = local variable */
554 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
555 if ((iptr->dst->varkind == LOCALVAR) &&
556 (iptr->dst->varnum == iptr->op1))
558 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
559 if (var->flags & INMEMORY) {
560 M_LLD(d, REG_SP, 8 * var->regoff);
562 M_INTMOVE(var->regoff,d);
564 store_reg_to_var_int(iptr->dst, d);
567 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
568 case ICMD_DLOAD: /* op1 = local variable */
570 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
571 if ((iptr->dst->varkind == LOCALVAR) &&
572 (iptr->dst->varnum == iptr->op1))
574 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
576 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
577 if (var->flags & INMEMORY) {
578 M_CCFLD(var->type, t2, d, REG_SP, 8 * var->regoff);
580 M_CCFLTMOVE(var->type, t2, var->regoff, d);
583 store_reg_to_var_flt(iptr->dst, d);
587 case ICMD_ISTORE: /* ..., value ==> ... */
588 case ICMD_LSTORE: /* op1 = local variable */
591 if ((src->varkind == LOCALVAR) &&
592 (src->varnum == iptr->op1))
594 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
595 if (var->flags & INMEMORY) {
596 var_to_reg_int(s1, src, REG_ITMP1);
597 M_LST(s1, REG_SP, 8 * var->regoff);
600 var_to_reg_int(s1, src, var->regoff);
601 M_INTMOVE(s1, var->regoff);
605 case ICMD_FSTORE: /* ..., value ==> ... */
606 case ICMD_DSTORE: /* op1 = local variable */
608 if ((src->varkind == LOCALVAR) &&
609 (src->varnum == iptr->op1))
611 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
613 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
614 if (var->flags & INMEMORY) {
615 var_to_reg_flt(s1, src, REG_FTMP1);
616 M_CCFST(t1, var->type, s1, REG_SP, 8 * var->regoff);
619 var_to_reg_flt(s1, src, var->regoff);
620 M_CCFLTMOVE(t1, var->type, s1, var->regoff);
626 /* pop/dup/swap operations ********************************************/
628 /* attention: double and longs are only one entry in CACAO ICMDs */
630 case ICMD_POP: /* ..., value ==> ... */
631 case ICMD_POP2: /* ..., value, value ==> ... */
634 case ICMD_DUP: /* ..., a ==> ..., a, a */
635 M_COPY(src, iptr->dst);
638 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
640 M_COPY(src, iptr->dst);
641 M_COPY(src->prev, iptr->dst->prev);
642 M_COPY(iptr->dst, iptr->dst->prev->prev);
645 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
647 M_COPY(src, iptr->dst);
648 M_COPY(src->prev, iptr->dst->prev);
649 M_COPY(src->prev->prev, iptr->dst->prev->prev);
650 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
653 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
655 M_COPY(src, iptr->dst);
656 M_COPY(src->prev, iptr->dst->prev);
659 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
661 M_COPY(src, iptr->dst);
662 M_COPY(src->prev, iptr->dst->prev);
663 M_COPY(src->prev->prev, iptr->dst->prev->prev);
664 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
665 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
668 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
670 M_COPY(src, iptr->dst);
671 M_COPY(src->prev, iptr->dst->prev);
672 M_COPY(src->prev->prev, iptr->dst->prev->prev);
673 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
674 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
675 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
678 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
680 M_COPY(src, iptr->dst->prev);
681 M_COPY(src->prev, iptr->dst);
685 /* integer operations *************************************************/
687 case ICMD_INEG: /* ..., value ==> ..., - value */
689 var_to_reg_int(s1, src, REG_ITMP1);
690 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
691 M_ISUB(REG_ZERO, s1, d);
692 store_reg_to_var_int(iptr->dst, d);
695 case ICMD_LNEG: /* ..., value ==> ..., - value */
697 var_to_reg_int(s1, src, REG_ITMP1);
698 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
699 M_LSUB(REG_ZERO, s1, d);
700 store_reg_to_var_int(iptr->dst, d);
703 case ICMD_I2L: /* ..., value ==> ..., value */
705 var_to_reg_int(s1, src, REG_ITMP1);
706 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
708 store_reg_to_var_int(iptr->dst, d);
711 case ICMD_L2I: /* ..., value ==> ..., value */
713 var_to_reg_int(s1, src, REG_ITMP1);
714 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
715 M_ISLL_IMM(s1, 0, d );
716 store_reg_to_var_int(iptr->dst, d);
719 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
721 var_to_reg_int(s1, src, REG_ITMP1);
722 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
723 M_LSLL_IMM(s1, 56, d);
724 M_LSRA_IMM( d, 56, d);
725 store_reg_to_var_int(iptr->dst, d);
728 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
730 var_to_reg_int(s1, src, REG_ITMP1);
731 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
733 store_reg_to_var_int(iptr->dst, d);
736 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
738 var_to_reg_int(s1, src, REG_ITMP1);
739 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
740 M_LSLL_IMM(s1, 48, d);
741 M_LSRA_IMM( d, 48, d);
742 store_reg_to_var_int(iptr->dst, d);
746 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
748 var_to_reg_int(s1, src->prev, REG_ITMP1);
749 var_to_reg_int(s2, src, REG_ITMP2);
750 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
752 store_reg_to_var_int(iptr->dst, d);
755 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
756 /* val.i = constant */
758 var_to_reg_int(s1, src, REG_ITMP1);
759 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
760 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
761 M_IADD_IMM(s1, iptr->val.i, d);
763 ICONST(REG_ITMP2, iptr->val.i);
764 M_IADD(s1, REG_ITMP2, d);
766 store_reg_to_var_int(iptr->dst, d);
769 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
771 var_to_reg_int(s1, src->prev, REG_ITMP1);
772 var_to_reg_int(s2, src, REG_ITMP2);
773 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
775 store_reg_to_var_int(iptr->dst, d);
778 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
779 /* val.l = constant */
781 var_to_reg_int(s1, src, REG_ITMP1);
782 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
783 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
784 M_LADD_IMM(s1, iptr->val.l, d);
786 LCONST(REG_ITMP2, iptr->val.l);
787 M_LADD(s1, REG_ITMP2, d);
789 store_reg_to_var_int(iptr->dst, d);
792 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
794 var_to_reg_int(s1, src->prev, REG_ITMP1);
795 var_to_reg_int(s2, src, REG_ITMP2);
796 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
798 store_reg_to_var_int(iptr->dst, d);
801 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
802 /* val.i = constant */
804 var_to_reg_int(s1, src, REG_ITMP1);
805 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
806 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
807 M_IADD_IMM(s1, -iptr->val.i, d);
809 ICONST(REG_ITMP2, iptr->val.i);
810 M_ISUB(s1, REG_ITMP2, d);
812 store_reg_to_var_int(iptr->dst, d);
815 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
817 var_to_reg_int(s1, src->prev, REG_ITMP1);
818 var_to_reg_int(s2, src, REG_ITMP2);
819 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
821 store_reg_to_var_int(iptr->dst, d);
824 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
825 /* val.l = constant */
827 var_to_reg_int(s1, src, REG_ITMP1);
828 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
829 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
830 M_LADD_IMM(s1, -iptr->val.l, d);
832 LCONST(REG_ITMP2, iptr->val.l);
833 M_LSUB(s1, REG_ITMP2, d);
835 store_reg_to_var_int(iptr->dst, d);
838 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
840 var_to_reg_int(s1, src->prev, REG_ITMP1);
841 var_to_reg_int(s2, src, REG_ITMP2);
842 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
847 store_reg_to_var_int(iptr->dst, d);
850 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
851 /* val.i = constant */
853 var_to_reg_int(s1, src, REG_ITMP1);
854 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
855 ICONST(REG_ITMP2, iptr->val.i);
856 M_IMUL(s1, REG_ITMP2);
860 store_reg_to_var_int(iptr->dst, d);
863 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
865 var_to_reg_int(s1, src->prev, REG_ITMP1);
866 var_to_reg_int(s2, src, REG_ITMP2);
867 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
872 store_reg_to_var_int(iptr->dst, d);
875 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
876 /* val.l = constant */
878 var_to_reg_int(s1, src, REG_ITMP1);
879 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
880 LCONST(REG_ITMP2, iptr->val.l);
881 M_LMUL(s1, REG_ITMP2);
885 store_reg_to_var_int(iptr->dst, d);
888 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
890 var_to_reg_int(s1, src->prev, REG_ITMP1);
891 var_to_reg_int(s2, src, REG_ITMP2);
892 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
898 store_reg_to_var_int(iptr->dst, d);
901 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
903 var_to_reg_int(s1, src->prev, REG_ITMP1);
904 var_to_reg_int(s2, src, REG_ITMP2);
905 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
911 store_reg_to_var_int(iptr->dst, d);
914 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
916 var_to_reg_int(s1, src->prev, REG_ITMP1);
917 var_to_reg_int(s2, src, REG_ITMP2);
918 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
924 store_reg_to_var_int(iptr->dst, d);
927 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
929 var_to_reg_int(s1, src->prev, REG_ITMP1);
930 var_to_reg_int(s2, src, REG_ITMP2);
931 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
937 store_reg_to_var_int(iptr->dst, d);
940 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
941 case ICMD_LDIVPOW2: /* val.i = constant */
943 var_to_reg_int(s1, src, REG_ITMP1);
944 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
945 M_LSRA_IMM(s1, 63, REG_ITMP2);
946 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
947 M_LADD(s1, REG_ITMP2, REG_ITMP2);
948 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
949 store_reg_to_var_int(iptr->dst, d);
952 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
954 var_to_reg_int(s1, src->prev, REG_ITMP1);
955 var_to_reg_int(s2, src, REG_ITMP2);
956 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
958 store_reg_to_var_int(iptr->dst, d);
961 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
962 /* val.i = constant */
964 var_to_reg_int(s1, src, REG_ITMP1);
965 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
966 M_ISLL_IMM(s1, iptr->val.i, d);
967 store_reg_to_var_int(iptr->dst, d);
970 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
972 var_to_reg_int(s1, src->prev, REG_ITMP1);
973 var_to_reg_int(s2, src, REG_ITMP2);
974 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
976 store_reg_to_var_int(iptr->dst, d);
979 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
980 /* val.i = constant */
982 var_to_reg_int(s1, src, REG_ITMP1);
983 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
984 M_ISRA_IMM(s1, iptr->val.i, d);
985 store_reg_to_var_int(iptr->dst, d);
988 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
990 var_to_reg_int(s1, src->prev, REG_ITMP1);
991 var_to_reg_int(s2, src, REG_ITMP2);
992 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
994 store_reg_to_var_int(iptr->dst, d);
997 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
998 /* val.i = constant */
1000 var_to_reg_int(s1, src, REG_ITMP1);
1001 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1002 M_ISRL_IMM(s1, iptr->val.i, d);
1003 store_reg_to_var_int(iptr->dst, d);
1006 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1008 var_to_reg_int(s1, src->prev, REG_ITMP1);
1009 var_to_reg_int(s2, src, REG_ITMP2);
1010 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1012 store_reg_to_var_int(iptr->dst, d);
1015 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1016 /* val.i = constant */
1018 var_to_reg_int(s1, src, REG_ITMP1);
1019 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1020 M_LSLL_IMM(s1, iptr->val.i, d);
1021 store_reg_to_var_int(iptr->dst, d);
1024 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1026 var_to_reg_int(s1, src->prev, REG_ITMP1);
1027 var_to_reg_int(s2, src, REG_ITMP2);
1028 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1030 store_reg_to_var_int(iptr->dst, d);
1033 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1034 /* val.i = constant */
1036 var_to_reg_int(s1, src, REG_ITMP1);
1037 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1038 M_LSRA_IMM(s1, iptr->val.i, d);
1039 store_reg_to_var_int(iptr->dst, d);
1042 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1044 var_to_reg_int(s1, src->prev, REG_ITMP1);
1045 var_to_reg_int(s2, src, REG_ITMP2);
1046 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1048 store_reg_to_var_int(iptr->dst, d);
1051 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1052 /* val.i = constant */
1054 var_to_reg_int(s1, src, REG_ITMP1);
1055 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1056 M_LSRL_IMM(s1, iptr->val.i, d);
1057 store_reg_to_var_int(iptr->dst, d);
1060 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1063 var_to_reg_int(s1, src->prev, REG_ITMP1);
1064 var_to_reg_int(s2, src, REG_ITMP2);
1065 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1067 store_reg_to_var_int(iptr->dst, d);
1070 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1071 /* val.i = constant */
1073 var_to_reg_int(s1, src, REG_ITMP1);
1074 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1075 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1076 M_AND_IMM(s1, iptr->val.i, d);
1078 ICONST(REG_ITMP2, iptr->val.i);
1079 M_AND(s1, REG_ITMP2, d);
1081 store_reg_to_var_int(iptr->dst, d);
1084 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1085 /* val.i = constant */
1087 var_to_reg_int(s1, src, REG_ITMP1);
1088 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1090 M_MOV(s1, REG_ITMP1);
1093 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1094 M_AND_IMM(s1, iptr->val.i, d);
1097 M_ISUB(REG_ZERO, s1, d);
1098 M_AND_IMM(d, iptr->val.i, d);
1100 ICONST(REG_ITMP2, iptr->val.i);
1101 M_AND(s1, REG_ITMP2, d);
1104 M_ISUB(REG_ZERO, s1, d);
1105 M_AND(d, REG_ITMP2, d);
1107 M_ISUB(REG_ZERO, d, d);
1108 store_reg_to_var_int(iptr->dst, d);
1111 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1112 /* val.l = constant */
1114 var_to_reg_int(s1, src, REG_ITMP1);
1115 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1116 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1117 M_AND_IMM(s1, iptr->val.l, d);
1119 LCONST(REG_ITMP2, iptr->val.l);
1120 M_AND(s1, REG_ITMP2, d);
1122 store_reg_to_var_int(iptr->dst, d);
1125 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1126 /* val.l = constant */
1128 var_to_reg_int(s1, src, REG_ITMP1);
1129 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1131 M_MOV(s1, REG_ITMP1);
1134 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1135 M_AND_IMM(s1, iptr->val.l, d);
1138 M_LSUB(REG_ZERO, s1, d);
1139 M_AND_IMM(d, iptr->val.l, d);
1141 LCONST(REG_ITMP2, iptr->val.l);
1142 M_AND(s1, REG_ITMP2, d);
1145 M_LSUB(REG_ZERO, s1, d);
1146 M_AND(d, REG_ITMP2, d);
1148 M_LSUB(REG_ZERO, d, d);
1149 store_reg_to_var_int(iptr->dst, d);
1152 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1155 var_to_reg_int(s1, src->prev, REG_ITMP1);
1156 var_to_reg_int(s2, src, REG_ITMP2);
1157 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1159 store_reg_to_var_int(iptr->dst, d);
1162 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1163 /* val.i = constant */
1165 var_to_reg_int(s1, src, REG_ITMP1);
1166 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1167 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1168 M_OR_IMM(s1, iptr->val.i, d);
1170 ICONST(REG_ITMP2, iptr->val.i);
1171 M_OR(s1, REG_ITMP2, d);
1173 store_reg_to_var_int(iptr->dst, d);
1176 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1177 /* val.l = constant */
1179 var_to_reg_int(s1, src, REG_ITMP1);
1180 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1181 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1182 M_OR_IMM(s1, iptr->val.l, d);
1184 LCONST(REG_ITMP2, iptr->val.l);
1185 M_OR(s1, REG_ITMP2, d);
1187 store_reg_to_var_int(iptr->dst, d);
1190 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1193 var_to_reg_int(s1, src->prev, REG_ITMP1);
1194 var_to_reg_int(s2, src, REG_ITMP2);
1195 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1197 store_reg_to_var_int(iptr->dst, d);
1200 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1201 /* val.i = constant */
1203 var_to_reg_int(s1, src, REG_ITMP1);
1204 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1205 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1206 M_XOR_IMM(s1, iptr->val.i, d);
1208 ICONST(REG_ITMP2, iptr->val.i);
1209 M_XOR(s1, REG_ITMP2, d);
1211 store_reg_to_var_int(iptr->dst, d);
1214 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1215 /* val.l = constant */
1217 var_to_reg_int(s1, src, REG_ITMP1);
1218 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1219 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1220 M_XOR_IMM(s1, iptr->val.l, d);
1222 LCONST(REG_ITMP2, iptr->val.l);
1223 M_XOR(s1, REG_ITMP2, d);
1225 store_reg_to_var_int(iptr->dst, d);
1229 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1231 var_to_reg_int(s1, src->prev, REG_ITMP1);
1232 var_to_reg_int(s2, src, REG_ITMP2);
1233 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1234 M_CMPLT(s1, s2, REG_ITMP3);
1235 M_CMPLT(s2, s1, REG_ITMP1);
1236 M_LSUB(REG_ITMP1, REG_ITMP3, d);
1237 store_reg_to_var_int(iptr->dst, d);
1241 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1242 /* op1 = variable, val.i = constant */
1244 var = &(rd->locals[iptr->op1][TYPE_INT]);
1245 if (var->flags & INMEMORY) {
1247 M_LLD(s1, REG_SP, var->regoff * 8);
1250 M_IADD_IMM(s1, iptr->val.i, s1);
1251 if (var->flags & INMEMORY)
1252 M_LST(s1, REG_SP, var->regoff * 8);
1256 /* floating operations ************************************************/
1258 case ICMD_FNEG: /* ..., value ==> ..., - value */
1260 var_to_reg_flt(s1, src, REG_FTMP1);
1261 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1263 store_reg_to_var_flt(iptr->dst, d);
1266 case ICMD_DNEG: /* ..., value ==> ..., - value */
1268 var_to_reg_flt(s1, src, REG_FTMP1);
1269 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1271 store_reg_to_var_flt(iptr->dst, d);
1274 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1276 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1277 var_to_reg_flt(s2, src, REG_FTMP2);
1278 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1280 store_reg_to_var_flt(iptr->dst, d);
1283 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1285 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1286 var_to_reg_flt(s2, src, REG_FTMP2);
1287 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1289 store_reg_to_var_flt(iptr->dst, d);
1292 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1294 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1295 var_to_reg_flt(s2, src, REG_FTMP2);
1296 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1298 store_reg_to_var_flt(iptr->dst, d);
1301 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1303 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1304 var_to_reg_flt(s2, src, REG_FTMP2);
1305 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1307 store_reg_to_var_flt(iptr->dst, d);
1310 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1312 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1313 var_to_reg_flt(s2, src, REG_FTMP2);
1314 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1316 store_reg_to_var_flt(iptr->dst, d);
1319 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1321 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1322 var_to_reg_flt(s2, src, REG_FTMP2);
1323 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1325 store_reg_to_var_flt(iptr->dst, d);
1328 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1330 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1331 var_to_reg_flt(s2, src, REG_FTMP2);
1332 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1334 store_reg_to_var_flt(iptr->dst, d);
1337 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1339 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1340 var_to_reg_flt(s2, src, REG_FTMP2);
1341 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1343 store_reg_to_var_flt(iptr->dst, d);
1347 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1349 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1350 var_to_reg_flt(s2, src, REG_FTMP2);
1351 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1352 M_FDIV(s1,s2, REG_FTMP3);
1353 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1354 M_CVTLF(REG_FTMP3, REG_FTMP3);
1355 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1356 M_FSUB(s1, REG_FTMP3, d);
1357 store_reg_to_var_flt(iptr->dst, d);
1360 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1362 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1363 var_to_reg_flt(s2, src, REG_FTMP2);
1364 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1365 M_DDIV(s1,s2, REG_FTMP3);
1366 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1367 M_CVTLD(REG_FTMP3, REG_FTMP3);
1368 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1369 M_DSUB(s1, REG_FTMP3, d);
1370 store_reg_to_var_flt(iptr->dst, d);
1374 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1376 var_to_reg_int(s1, src, REG_ITMP1);
1377 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1380 store_reg_to_var_flt(iptr->dst, d);
1383 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1385 var_to_reg_int(s1, src, REG_ITMP1);
1386 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1389 store_reg_to_var_flt(iptr->dst, d);
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);
1432 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1434 var_to_reg_flt(s1, src, REG_FTMP1);
1435 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1437 store_reg_to_var_flt(iptr->dst, d);
1440 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1442 var_to_reg_flt(s1, src, REG_FTMP1);
1443 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1445 store_reg_to_var_flt(iptr->dst, d);
1448 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1450 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1451 var_to_reg_flt(s2, src, REG_FTMP2);
1452 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1455 M_LADD_IMM(REG_ZERO, 1, d);
1459 M_LSUB_IMM(REG_ZERO, 1, d);
1460 M_CMOVT(REG_ZERO, d);
1461 store_reg_to_var_int(iptr->dst, d);
1464 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1466 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1467 var_to_reg_flt(s2, src, REG_FTMP2);
1468 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1471 M_LADD_IMM(REG_ZERO, 1, d);
1475 M_LSUB_IMM(REG_ZERO, 1, d);
1476 M_CMOVT(REG_ZERO, d);
1477 store_reg_to_var_int(iptr->dst, d);
1480 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1482 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1483 var_to_reg_flt(s2, src, REG_FTMP2);
1484 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1487 M_LSUB_IMM(REG_ZERO, 1, d);
1491 M_LADD_IMM(REG_ZERO, 1, d);
1492 M_CMOVT(REG_ZERO, d);
1493 store_reg_to_var_int(iptr->dst, d);
1496 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1498 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1499 var_to_reg_flt(s2, src, REG_FTMP2);
1500 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1503 M_LSUB_IMM(REG_ZERO, 1, d);
1507 M_LADD_IMM(REG_ZERO, 1, d);
1508 M_CMOVT(REG_ZERO, d);
1509 store_reg_to_var_int(iptr->dst, d);
1513 /* memory operations **************************************************/
1515 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1517 var_to_reg_int(s1, src, REG_ITMP1);
1518 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1519 gen_nullptr_check(s1);
1520 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1521 store_reg_to_var_int(iptr->dst, d);
1524 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1526 var_to_reg_int(s1, src->prev, REG_ITMP1);
1527 var_to_reg_int(s2, src, REG_ITMP2);
1528 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1529 if (iptr->op1 == 0) {
1530 gen_nullptr_check(s1);
1533 M_AADD(s2, s1, REG_ITMP3);
1534 M_BLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1535 store_reg_to_var_int(iptr->dst, d);
1538 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1540 var_to_reg_int(s1, src->prev, REG_ITMP1);
1541 var_to_reg_int(s2, src, REG_ITMP2);
1542 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1543 if (iptr->op1 == 0) {
1544 gen_nullptr_check(s1);
1547 M_AADD(s2, s1, REG_ITMP3);
1548 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1549 M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1550 store_reg_to_var_int(iptr->dst, d);
1553 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1555 var_to_reg_int(s1, src->prev, REG_ITMP1);
1556 var_to_reg_int(s2, src, REG_ITMP2);
1557 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1558 if (iptr->op1 == 0) {
1559 gen_nullptr_check(s1);
1562 M_AADD(s2, s1, REG_ITMP3);
1563 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1564 M_SLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1565 store_reg_to_var_int(iptr->dst, d);
1568 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1570 var_to_reg_int(s1, src->prev, REG_ITMP1);
1571 var_to_reg_int(s2, src, REG_ITMP2);
1572 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1573 if (iptr->op1 == 0) {
1574 gen_nullptr_check(s1);
1577 M_ASLL_IMM(s2, 2, REG_ITMP3);
1578 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1579 M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
1580 store_reg_to_var_int(iptr->dst, d);
1583 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1585 var_to_reg_int(s1, src->prev, REG_ITMP1);
1586 var_to_reg_int(s2, src, REG_ITMP2);
1587 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1588 if (iptr->op1 == 0) {
1589 gen_nullptr_check(s1);
1592 M_ASLL_IMM(s2, 3, REG_ITMP3);
1593 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1594 M_LLD(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
1595 store_reg_to_var_int(iptr->dst, d);
1598 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1600 var_to_reg_int(s1, src->prev, REG_ITMP1);
1601 var_to_reg_int(s2, src, REG_ITMP2);
1602 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1603 if (iptr->op1 == 0) {
1604 gen_nullptr_check(s1);
1607 M_ASLL_IMM(s2, 2, REG_ITMP3);
1608 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1609 M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
1610 store_reg_to_var_flt(iptr->dst, d);
1613 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1615 var_to_reg_int(s1, src->prev, REG_ITMP1);
1616 var_to_reg_int(s2, src, REG_ITMP2);
1617 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1618 if (iptr->op1 == 0) {
1619 gen_nullptr_check(s1);
1622 M_ASLL_IMM(s2, 3, REG_ITMP3);
1623 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1624 M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
1625 store_reg_to_var_flt(iptr->dst, d);
1628 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1630 var_to_reg_int(s1, src->prev, REG_ITMP1);
1631 var_to_reg_int(s2, src, REG_ITMP2);
1632 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1633 if (iptr->op1 == 0) {
1634 gen_nullptr_check(s1);
1637 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1638 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1639 M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
1640 store_reg_to_var_int(iptr->dst, d);
1644 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1646 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1647 var_to_reg_int(s2, src->prev, REG_ITMP2);
1648 if (iptr->op1 == 0) {
1649 gen_nullptr_check(s1);
1652 M_AADD(s2, s1, REG_ITMP1);
1653 var_to_reg_int(s3, src, REG_ITMP3);
1654 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1657 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1658 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1660 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1661 var_to_reg_int(s2, src->prev, REG_ITMP2);
1662 if (iptr->op1 == 0) {
1663 gen_nullptr_check(s1);
1666 M_AADD(s2, s1, REG_ITMP1);
1667 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1668 var_to_reg_int(s3, src, REG_ITMP3);
1669 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1672 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1674 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1675 var_to_reg_int(s2, src->prev, REG_ITMP2);
1676 if (iptr->op1 == 0) {
1677 gen_nullptr_check(s1);
1680 M_ASLL_IMM(s2, 2, REG_ITMP2);
1681 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1682 var_to_reg_int(s3, src, REG_ITMP3);
1683 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1686 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1688 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1689 var_to_reg_int(s2, src->prev, REG_ITMP2);
1690 if (iptr->op1 == 0) {
1691 gen_nullptr_check(s1);
1694 M_ASLL_IMM(s2, 3, REG_ITMP2);
1695 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1696 var_to_reg_int(s3, src, REG_ITMP3);
1697 M_LST_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1700 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1702 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1703 var_to_reg_int(s2, src->prev, REG_ITMP2);
1704 if (iptr->op1 == 0) {
1705 gen_nullptr_check(s1);
1708 M_ASLL_IMM(s2, 2, REG_ITMP2);
1709 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1710 var_to_reg_flt(s3, src, REG_FTMP1);
1711 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1714 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1716 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1717 var_to_reg_int(s2, src->prev, REG_ITMP2);
1718 if (iptr->op1 == 0) {
1719 gen_nullptr_check(s1);
1722 M_ASLL_IMM(s2, 3, REG_ITMP2);
1723 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1724 var_to_reg_flt(s3, src, REG_FTMP1);
1725 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1729 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1731 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1732 var_to_reg_int(s2, src->prev, REG_ITMP2);
1733 if (iptr->op1 == 0) {
1734 gen_nullptr_check(s1);
1737 var_to_reg_int(s3, src, REG_ITMP3);
1739 M_MOV(s1, rd->argintregs[0]);
1740 M_MOV(s3, rd->argintregs[1]);
1741 disp = dseg_addaddress(cd, BUILTIN_canstore);
1742 M_ALD(REG_ITMP3, REG_PV, disp);
1743 M_JSR(REG_RA, REG_ITMP3);
1746 M_BEQZ(REG_RESULT, 0);
1747 codegen_addxstorerefs(cd, mcodeptr);
1750 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1751 var_to_reg_int(s2, src->prev, REG_ITMP2);
1752 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1753 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1754 var_to_reg_int(s3, src, REG_ITMP3);
1755 M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1759 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1761 var_to_reg_int(s1, src->prev, REG_ITMP1);
1762 var_to_reg_int(s2, src, REG_ITMP2);
1763 if (iptr->op1 == 0) {
1764 gen_nullptr_check(s1);
1767 M_AADD(s2, s1, REG_ITMP1);
1768 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1771 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1772 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1774 var_to_reg_int(s1, src->prev, REG_ITMP1);
1775 var_to_reg_int(s2, src, REG_ITMP2);
1776 if (iptr->op1 == 0) {
1777 gen_nullptr_check(s1);
1780 M_AADD(s2, s1, REG_ITMP1);
1781 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1782 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
1785 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1787 var_to_reg_int(s1, src->prev, REG_ITMP1);
1788 var_to_reg_int(s2, src, REG_ITMP2);
1789 if (iptr->op1 == 0) {
1790 gen_nullptr_check(s1);
1793 M_ASLL_IMM(s2, 2, REG_ITMP2);
1794 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1795 M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1798 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1800 var_to_reg_int(s1, src->prev, REG_ITMP1);
1801 var_to_reg_int(s2, src, REG_ITMP2);
1802 if (iptr->op1 == 0) {
1803 gen_nullptr_check(s1);
1806 M_ASLL_IMM(s2, 3, REG_ITMP2);
1807 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1808 M_LST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1811 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1813 var_to_reg_int(s1, src->prev, REG_ITMP1);
1814 var_to_reg_int(s2, src, REG_ITMP2);
1815 if (iptr->op1 == 0) {
1816 gen_nullptr_check(s1);
1819 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1820 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1821 M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1825 case ICMD_GETSTATIC: /* ... ==> ..., value */
1826 /* op1 = type, val.a = field address */
1829 disp = dseg_addaddress(cd, NULL);
1831 codegen_addpatchref(cd, mcodeptr,
1832 PATCHER_get_putstatic,
1833 (unresolved_field *) iptr->target, disp);
1835 if (opt_showdisassemble) {
1840 fieldinfo *fi = iptr->val.a;
1842 disp = dseg_addaddress(cd, &(fi->value));
1844 if (!(fi->class->state & CLASS_INITIALIZED)) {
1845 codegen_addpatchref(cd, mcodeptr,
1846 PATCHER_clinit, fi->class, 0);
1848 if (opt_showdisassemble) {
1854 M_ALD(REG_ITMP1, REG_PV, disp);
1855 switch (iptr->op1) {
1857 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1858 M_ILD_INTERN(d, REG_ITMP1, 0);
1859 store_reg_to_var_int(iptr->dst, d);
1862 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1863 M_LLD_INTERN(d, REG_ITMP1, 0);
1864 store_reg_to_var_int(iptr->dst, d);
1867 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1868 M_ALD_INTERN(d, REG_ITMP1, 0);
1869 store_reg_to_var_int(iptr->dst, d);
1872 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1873 M_FLD_INTERN(d, REG_ITMP1, 0);
1874 store_reg_to_var_flt(iptr->dst, d);
1877 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1878 M_DLD_INTERN(d, REG_ITMP1, 0);
1879 store_reg_to_var_flt(iptr->dst, d);
1884 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1885 /* op1 = type, val.a = field address */
1888 disp = dseg_addaddress(cd, NULL);
1890 codegen_addpatchref(cd, mcodeptr,
1891 PATCHER_get_putstatic,
1892 (unresolved_field *) iptr->target, disp);
1894 if (opt_showdisassemble) {
1899 fieldinfo *fi = iptr->val.a;
1901 disp = dseg_addaddress(cd, &(fi->value));
1903 if (!(fi->class->state & CLASS_INITIALIZED)) {
1904 codegen_addpatchref(cd, mcodeptr,
1905 PATCHER_clinit, fi->class, 0);
1907 if (opt_showdisassemble) {
1913 M_ALD(REG_ITMP1, REG_PV, disp);
1914 switch (iptr->op1) {
1916 var_to_reg_int(s2, src, REG_ITMP2);
1917 M_IST_INTERN(s2, REG_ITMP1, 0);
1920 var_to_reg_int(s2, src, REG_ITMP2);
1921 M_LST_INTERN(s2, REG_ITMP1, 0);
1924 var_to_reg_int(s2, src, REG_ITMP2);
1925 M_AST_INTERN(s2, REG_ITMP1, 0);
1928 var_to_reg_flt(s2, src, REG_FTMP2);
1929 M_FST_INTERN(s2, REG_ITMP1, 0);
1932 var_to_reg_flt(s2, src, REG_FTMP2);
1933 M_DST_INTERN(s2, REG_ITMP1, 0);
1938 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1939 /* val = value (in current instruction) */
1940 /* op1 = type, val.a = field address (in */
1941 /* following NOP) */
1943 if (!iptr[1].val.a) {
1944 disp = dseg_addaddress(cd, NULL);
1946 codegen_addpatchref(cd, mcodeptr,
1947 PATCHER_get_putstatic,
1948 (unresolved_field *) iptr[1].target, disp);
1950 if (opt_showdisassemble) {
1955 fieldinfo *fi = iptr[1].val.a;
1957 disp = dseg_addaddress(cd, &(fi->value));
1959 if (!(fi->class->state & CLASS_INITIALIZED)) {
1960 codegen_addpatchref(cd, mcodeptr,
1961 PATCHER_clinit, fi->class, 0);
1963 if (opt_showdisassemble) {
1969 M_ALD(REG_ITMP1, REG_PV, disp);
1970 switch (iptr->op1) {
1972 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1975 M_LST_INTERN(REG_ZERO, REG_ITMP1, 0);
1978 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1981 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1984 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1990 case ICMD_GETFIELD: /* ... ==> ..., value */
1991 /* op1 = type, val.i = field offset */
1993 var_to_reg_int(s1, src, REG_ITMP1);
1994 gen_nullptr_check(s1);
1997 codegen_addpatchref(cd, mcodeptr,
1998 PATCHER_get_putfield,
1999 (unresolved_field *) iptr->target, 0);
2001 if (opt_showdisassemble) {
2008 a = ((fieldinfo *) (iptr->val.a))->offset;
2011 switch (iptr->op1) {
2013 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2015 store_reg_to_var_int(iptr->dst, d);
2018 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2020 store_reg_to_var_int(iptr->dst, d);
2023 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2025 store_reg_to_var_int(iptr->dst, d);
2028 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2030 store_reg_to_var_flt(iptr->dst, d);
2033 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2035 store_reg_to_var_flt(iptr->dst, d);
2040 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2041 /* op1 = type, val.a = field address */
2043 var_to_reg_int(s1, src->prev, REG_ITMP1);
2044 gen_nullptr_check(s1);
2046 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2047 var_to_reg_int(s2, src, REG_ITMP2);
2049 var_to_reg_flt(s2, src, REG_FTMP2);
2053 codegen_addpatchref(cd, mcodeptr,
2054 PATCHER_get_putfield,
2055 (unresolved_field *) iptr->target, 0);
2057 if (opt_showdisassemble) {
2064 a = ((fieldinfo *) (iptr->val.a))->offset;
2067 switch (iptr->op1) {
2086 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2087 /* val = value (in current instruction) */
2088 /* op1 = type, val.a = field address (in */
2089 /* following NOP) */
2091 var_to_reg_int(s1, src, REG_ITMP1);
2092 gen_nullptr_check(s1);
2094 if (!iptr[1].val.a) {
2095 codegen_addpatchref(cd, mcodeptr,
2096 PATCHER_get_putfield,
2097 (unresolved_field *) iptr[1].target, 0);
2099 if (opt_showdisassemble) {
2106 a = ((fieldinfo *) (iptr[1].val.a))->offset;
2109 switch (iptr[1].op1) {
2111 M_IST(REG_ZERO, s1, a);
2114 M_LST(REG_ZERO, s1, a);
2117 M_AST(REG_ZERO, s1, a);
2120 M_FST(REG_ZERO, s1, a);
2123 M_DST(REG_ZERO, s1, a);
2129 /* branch operations **************************************************/
2131 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2133 var_to_reg_int(s1, src, REG_ITMP1);
2134 M_INTMOVE(s1, REG_ITMP1_XPTR);
2136 #ifdef ENABLE_VERIFIER
2138 codegen_addpatchref(cd, mcodeptr,
2139 PATCHER_athrow_areturn,
2140 (unresolved_class *) iptr->val.a, 0);
2142 if (opt_showdisassemble) {
2146 #endif /* ENABLE_VERIFIER */
2148 disp = dseg_addaddress(cd, asm_handle_exception);
2149 M_ALD(REG_ITMP2, REG_PV, disp);
2150 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2152 M_NOP; /* nop ensures that XPC is less than the end */
2153 /* of basic block */
2157 case ICMD_GOTO: /* ... ==> ... */
2158 /* op1 = target JavaVM pc */
2160 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2165 case ICMD_JSR: /* ... ==> ... */
2166 /* op1 = target JavaVM pc */
2168 dseg_addtarget(cd, (basicblock *) iptr->target);
2169 M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
2170 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2174 case ICMD_RET: /* ... ==> ... */
2175 /* op1 = local variable */
2176 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2177 if (var->flags & INMEMORY) {
2178 M_ALD(REG_ITMP1, REG_SP, var->regoff * 8);
2186 case ICMD_IFNULL: /* ..., value ==> ... */
2187 /* op1 = target JavaVM pc */
2189 var_to_reg_int(s1, src, REG_ITMP1);
2191 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2195 case ICMD_IFNONNULL: /* ..., value ==> ... */
2196 /* op1 = target JavaVM pc */
2198 var_to_reg_int(s1, src, REG_ITMP1);
2200 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2204 case ICMD_IFEQ: /* ..., value ==> ... */
2205 /* op1 = target JavaVM pc, val.i = constant */
2207 var_to_reg_int(s1, src, REG_ITMP1);
2208 if (iptr->val.i == 0) {
2211 ICONST(REG_ITMP2, iptr->val.i);
2212 M_BEQ(s1, REG_ITMP2, 0);
2214 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2218 case ICMD_IFLT: /* ..., value ==> ... */
2219 /* op1 = target JavaVM pc, val.i = constant */
2221 var_to_reg_int(s1, src, REG_ITMP1);
2222 if (iptr->val.i == 0) {
2225 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2226 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2228 ICONST(REG_ITMP2, iptr->val.i);
2229 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2231 M_BNEZ(REG_ITMP1, 0);
2233 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2237 case ICMD_IFLE: /* ..., value ==> ... */
2238 /* op1 = target JavaVM pc, val.i = constant */
2240 var_to_reg_int(s1, src, REG_ITMP1);
2241 if (iptr->val.i == 0) {
2245 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2246 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2247 M_BNEZ(REG_ITMP1, 0);
2250 ICONST(REG_ITMP2, iptr->val.i);
2251 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2252 M_BEQZ(REG_ITMP1, 0);
2255 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2259 case ICMD_IFNE: /* ..., value ==> ... */
2260 /* op1 = target JavaVM pc, val.i = constant */
2262 var_to_reg_int(s1, src, REG_ITMP1);
2263 if (iptr->val.i == 0) {
2267 ICONST(REG_ITMP2, iptr->val.i);
2268 M_BNE(s1, REG_ITMP2, 0);
2270 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2274 case ICMD_IFGT: /* ..., value ==> ... */
2275 /* op1 = target JavaVM pc, val.i = constant */
2277 var_to_reg_int(s1, src, REG_ITMP1);
2278 if (iptr->val.i == 0) {
2282 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2283 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2284 M_BEQZ(REG_ITMP1, 0);
2287 ICONST(REG_ITMP2, iptr->val.i);
2288 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2289 M_BNEZ(REG_ITMP1, 0);
2292 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2296 case ICMD_IFGE: /* ..., value ==> ... */
2297 /* op1 = target JavaVM pc, val.i = constant */
2299 var_to_reg_int(s1, src, REG_ITMP1);
2300 if (iptr->val.i == 0) {
2304 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2305 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2308 ICONST(REG_ITMP2, iptr->val.i);
2309 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2311 M_BEQZ(REG_ITMP1, 0);
2313 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2317 case ICMD_IF_LEQ: /* ..., value ==> ... */
2318 /* op1 = target JavaVM pc, val.l = constant */
2320 var_to_reg_int(s1, src, REG_ITMP1);
2321 if (iptr->val.l == 0) {
2325 LCONST(REG_ITMP2, iptr->val.l);
2326 M_BEQ(s1, REG_ITMP2, 0);
2328 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2332 case ICMD_IF_LLT: /* ..., value ==> ... */
2333 /* op1 = target JavaVM pc, val.l = constant */
2335 var_to_reg_int(s1, src, REG_ITMP1);
2336 if (iptr->val.l == 0) {
2340 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2341 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2344 LCONST(REG_ITMP2, iptr->val.l);
2345 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2347 M_BNEZ(REG_ITMP1, 0);
2349 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2353 case ICMD_IF_LLE: /* ..., value ==> ... */
2354 /* op1 = target JavaVM pc, val.l = constant */
2356 var_to_reg_int(s1, src, REG_ITMP1);
2357 if (iptr->val.l == 0) {
2361 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2362 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2363 M_BNEZ(REG_ITMP1, 0);
2366 LCONST(REG_ITMP2, iptr->val.l);
2367 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2368 M_BEQZ(REG_ITMP1, 0);
2371 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2375 case ICMD_IF_LNE: /* ..., value ==> ... */
2376 /* op1 = target JavaVM pc, val.l = constant */
2378 var_to_reg_int(s1, src, REG_ITMP1);
2379 if (iptr->val.l == 0) {
2383 LCONST(REG_ITMP2, iptr->val.l);
2384 M_BNE(s1, REG_ITMP2, 0);
2386 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2390 case ICMD_IF_LGT: /* ..., value ==> ... */
2391 /* op1 = target JavaVM pc, val.l = constant */
2393 var_to_reg_int(s1, src, REG_ITMP1);
2394 if (iptr->val.l == 0) {
2398 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2399 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2400 M_BEQZ(REG_ITMP1, 0);
2403 LCONST(REG_ITMP2, iptr->val.l);
2404 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2405 M_BNEZ(REG_ITMP1, 0);
2408 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2412 case ICMD_IF_LGE: /* ..., value ==> ... */
2413 /* op1 = target JavaVM pc, val.l = constant */
2415 var_to_reg_int(s1, src, REG_ITMP1);
2416 if (iptr->val.l == 0) {
2420 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2421 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2424 LCONST(REG_ITMP2, iptr->val.l);
2425 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2427 M_BEQZ(REG_ITMP1, 0);
2429 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2433 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2434 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2435 case ICMD_IF_ACMPEQ:
2437 var_to_reg_int(s1, src->prev, REG_ITMP1);
2438 var_to_reg_int(s2, src, REG_ITMP2);
2440 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2444 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2445 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2446 case ICMD_IF_ACMPNE:
2448 var_to_reg_int(s1, src->prev, REG_ITMP1);
2449 var_to_reg_int(s2, src, REG_ITMP2);
2451 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2455 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2456 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2458 var_to_reg_int(s1, src->prev, REG_ITMP1);
2459 var_to_reg_int(s2, src, REG_ITMP2);
2460 M_CMPLT(s1, s2, REG_ITMP1);
2461 M_BNEZ(REG_ITMP1, 0);
2462 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2466 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2467 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2469 var_to_reg_int(s1, src->prev, REG_ITMP1);
2470 var_to_reg_int(s2, src, REG_ITMP2);
2471 M_CMPGT(s1, s2, REG_ITMP1);
2472 M_BNEZ(REG_ITMP1, 0);
2473 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2477 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2478 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2480 var_to_reg_int(s1, src->prev, REG_ITMP1);
2481 var_to_reg_int(s2, src, REG_ITMP2);
2482 M_CMPGT(s1, s2, REG_ITMP1);
2483 M_BEQZ(REG_ITMP1, 0);
2484 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2488 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2489 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2491 var_to_reg_int(s1, src->prev, REG_ITMP1);
2492 var_to_reg_int(s2, src, REG_ITMP2);
2493 M_CMPLT(s1, s2, REG_ITMP1);
2494 M_BEQZ(REG_ITMP1, 0);
2495 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2499 #ifdef CONDITIONAL_LOADCONST
2500 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2502 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2505 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2506 /* val.i = constant */
2508 var_to_reg_int(s1, src, REG_ITMP1);
2509 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2511 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2512 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2513 M_CMPEQ(s1, REG_ZERO, d);
2514 store_reg_to_var_int(iptr->dst, d);
2517 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2518 M_CMPEQ(s1, REG_ZERO, d);
2520 store_reg_to_var_int(iptr->dst, d);
2524 M_MOV(s1, REG_ITMP1);
2527 ICONST(d, iptr[1].val.i);
2529 if ((s3 >= 0) && (s3 <= 255)) {
2530 M_CMOVEQ_IMM(s1, s3, d);
2532 ICONST(REG_ITMP3, s3);
2533 M_CMOVEQ(s1, REG_ITMP3, d);
2535 store_reg_to_var_int(iptr->dst, d);
2538 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2539 /* val.i = constant */
2541 var_to_reg_int(s1, src, REG_ITMP1);
2542 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2544 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2545 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2546 M_CMPEQ(s1, REG_ZERO, d);
2547 store_reg_to_var_int(iptr->dst, d);
2550 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2551 M_CMPEQ(s1, REG_ZERO, d);
2553 store_reg_to_var_int(iptr->dst, d);
2557 M_MOV(s1, REG_ITMP1);
2560 ICONST(d, iptr[1].val.i);
2562 if ((s3 >= 0) && (s3 <= 255)) {
2563 M_CMOVNE_IMM(s1, s3, d);
2565 ICONST(REG_ITMP3, s3);
2566 M_CMOVNE(s1, REG_ITMP3, d);
2568 store_reg_to_var_int(iptr->dst, d);
2571 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2572 /* val.i = constant */
2574 var_to_reg_int(s1, src, REG_ITMP1);
2575 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2577 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2578 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2579 M_CMPLT(s1, REG_ZERO, d);
2580 store_reg_to_var_int(iptr->dst, d);
2583 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2584 M_CMPLE(REG_ZERO, s1, d);
2585 store_reg_to_var_int(iptr->dst, d);
2589 M_MOV(s1, REG_ITMP1);
2592 ICONST(d, iptr[1].val.i);
2594 if ((s3 >= 0) && (s3 <= 255)) {
2595 M_CMOVLT_IMM(s1, s3, d);
2597 ICONST(REG_ITMP3, s3);
2598 M_CMOVLT(s1, REG_ITMP3, d);
2600 store_reg_to_var_int(iptr->dst, d);
2603 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2604 /* val.i = constant */
2606 var_to_reg_int(s1, src, REG_ITMP1);
2607 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2609 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2610 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2611 M_CMPLE(REG_ZERO, s1, d);
2612 store_reg_to_var_int(iptr->dst, d);
2615 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2616 M_CMPLT(s1, REG_ZERO, d);
2617 store_reg_to_var_int(iptr->dst, d);
2621 M_MOV(s1, REG_ITMP1);
2624 ICONST(d, iptr[1].val.i);
2626 if ((s3 >= 0) && (s3 <= 255)) {
2627 M_CMOVGE_IMM(s1, s3, d);
2629 ICONST(REG_ITMP3, s3);
2630 M_CMOVGE(s1, REG_ITMP3, d);
2632 store_reg_to_var_int(iptr->dst, d);
2635 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2636 /* val.i = constant */
2638 var_to_reg_int(s1, src, REG_ITMP1);
2639 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2641 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2642 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2643 M_CMPLT(REG_ZERO, s1, d);
2644 store_reg_to_var_int(iptr->dst, d);
2647 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2648 M_CMPLE(s1, REG_ZERO, d);
2649 store_reg_to_var_int(iptr->dst, d);
2653 M_MOV(s1, REG_ITMP1);
2656 ICONST(d, iptr[1].val.i);
2658 if ((s3 >= 0) && (s3 <= 255)) {
2659 M_CMOVGT_IMM(s1, s3, d);
2661 ICONST(REG_ITMP3, s3);
2662 M_CMOVGT(s1, REG_ITMP3, d);
2664 store_reg_to_var_int(iptr->dst, d);
2667 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2668 /* val.i = constant */
2670 var_to_reg_int(s1, src, REG_ITMP1);
2671 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2673 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2674 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2675 M_CMPLE(s1, REG_ZERO, d);
2676 store_reg_to_var_int(iptr->dst, d);
2679 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2680 M_CMPLT(REG_ZERO, s1, d);
2681 store_reg_to_var_int(iptr->dst, d);
2685 M_MOV(s1, REG_ITMP1);
2688 ICONST(d, iptr[1].val.i);
2690 if ((s3 >= 0) && (s3 <= 255)) {
2691 M_CMOVLE_IMM(s1, s3, d);
2693 ICONST(REG_ITMP3, s3);
2694 M_CMOVLE(s1, REG_ITMP3, d);
2696 store_reg_to_var_int(iptr->dst, d);
2701 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2704 var_to_reg_int(s1, src, REG_RESULT);
2705 M_INTMOVE(s1, REG_RESULT);
2706 goto nowperformreturn;
2708 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2710 var_to_reg_int(s1, src, REG_RESULT);
2711 M_INTMOVE(s1, REG_RESULT);
2713 #ifdef ENABLE_VERIFIER
2715 codegen_addpatchref(cd, mcodeptr,
2716 PATCHER_athrow_areturn,
2717 (unresolved_class *) iptr->val.a, 0);
2719 if (opt_showdisassemble) {
2723 #endif /* ENABLE_VERIFIER */
2724 goto nowperformreturn;
2726 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2728 var_to_reg_flt(s1, src, REG_FRESULT);
2730 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2731 M_TFLTMOVE(t, s1, REG_FRESULT);
2733 goto nowperformreturn;
2735 case ICMD_RETURN: /* ... ==> ... */
2741 p = parentargs_base;
2743 /* call trace function */
2746 M_LDA(REG_SP, REG_SP, -3 * 8);
2747 M_LST(REG_RA, REG_SP, 0 * 8);
2748 M_LST(REG_RESULT, REG_SP, 1 * 8);
2749 M_DST(REG_FRESULT, REG_SP, 2 * 8);
2751 disp = dseg_addaddress(cd, m);
2752 M_ALD(rd->argintregs[0], REG_PV, disp);
2753 M_MOV(REG_RESULT, rd->argintregs[1]);
2754 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2755 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
2757 disp = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2758 M_ALD(REG_ITMP3, REG_PV, disp);
2759 M_JSR(REG_RA, REG_ITMP3);
2762 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
2763 M_LLD(REG_RESULT, REG_SP, 1 * 8);
2764 M_LLD(REG_RA, REG_SP, 0 * 8);
2765 M_LDA(REG_SP, REG_SP, 3 * 8);
2768 #if defined(USE_THREADS)
2769 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2770 disp = dseg_addaddress(cd, (void *) builtin_monitorexit);
2771 M_ALD(REG_ITMP3, REG_PV, disp);
2773 /* we need to save the proper return value */
2775 switch (iptr->opc) {
2779 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2780 M_JSR(REG_RA, REG_ITMP3);
2781 M_LST(REG_RESULT, REG_SP, rd->memuse * 8); /* delay slot */
2785 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2786 M_JSR(REG_RA, REG_ITMP3);
2787 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8); /* delay slot */
2790 M_JSR(REG_RA, REG_ITMP3);
2791 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8); /* delay*/
2795 /* and now restore the proper return value */
2797 switch (iptr->opc) {
2801 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
2805 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
2811 /* restore return address */
2813 if (!m->isleafmethod) {
2814 p--; M_ALD(REG_RA, REG_SP, p * 8);
2817 /* restore saved registers */
2819 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2820 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
2822 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2823 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2826 /* deallocate stack and return */
2828 if (parentargs_base) {
2831 disp = parentargs_base * 8;
2832 lo = (short) (disp);
2833 hi = (short) (((disp) - lo) >> 16);
2837 M_LADD_IMM(REG_SP, lo, REG_SP); /* delay slot */
2839 M_LUI(REG_ITMP3,hi);
2840 M_LADD_IMM(REG_ITMP3,lo,REG_ITMP3);
2842 M_LADD(REG_ITMP3,REG_SP,REG_SP); /* delay slot */
2855 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2860 tptr = (void **) iptr->target;
2862 s4ptr = iptr->val.a;
2863 l = s4ptr[1]; /* low */
2864 i = s4ptr[2]; /* high */
2866 var_to_reg_int(s1, src, REG_ITMP1);
2868 {M_INTMOVE(s1, REG_ITMP1);}
2869 else if (l <= 32768) {
2870 M_IADD_IMM(s1, -l, REG_ITMP1);
2873 ICONST(REG_ITMP2, l);
2874 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2880 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
2881 M_BEQZ(REG_ITMP2, 0);
2882 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2883 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
2885 /* build jump table top down and use address of lowest entry */
2887 /* s4ptr += 3 + i; */
2891 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2892 dseg_addtarget(cd, (basicblock *) tptr[0]);
2897 /* length of dataseg after last dseg_addtarget is used by load */
2899 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2900 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2907 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2909 s4 i, /*l, */val, *s4ptr;
2912 tptr = (void **) iptr->target;
2914 s4ptr = iptr->val.a;
2915 /*l = s4ptr[0];*/ /* default */
2916 i = s4ptr[1]; /* count */
2918 MCODECHECK((i<<2)+8);
2919 var_to_reg_int(s1, src, REG_ITMP1);
2925 ICONST(REG_ITMP2, val);
2926 M_BEQ(s1, REG_ITMP2, 0);
2927 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2932 tptr = (void **) iptr->target;
2933 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2940 case ICMD_BUILTIN: /* ..., arg1 ==> ... */
2941 /* op1 = arg count val.a = builtintable entry */
2947 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2948 /* op1 = arg count, val.a = method pointer */
2950 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2951 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2952 case ICMD_INVOKEINTERFACE:
2957 unresolved_method *um = iptr->target;
2958 md = um->methodref->parseddesc.md;
2960 md = lm->parseddesc;
2964 s3 = md->paramcount;
2966 MCODECHECK((s3 << 1) + 64);
2968 /* copy arguments to registers or stack location */
2970 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2971 if (src->varkind == ARGVAR)
2973 if (IS_INT_LNG_TYPE(src->type)) {
2974 if (!md->params[s3].inmemory) {
2975 s1 = rd->argintregs[md->params[s3].regoff];
2976 var_to_reg_int(d, src, s1);
2979 var_to_reg_int(d, src, REG_ITMP1);
2980 M_LST(d, REG_SP, md->params[s3].regoff * 8);
2984 if (!md->params[s3].inmemory) {
2985 s1 = rd->argfltregs[md->params[s3].regoff];
2986 var_to_reg_flt(d, src, s1);
2987 M_TFLTMOVE(src->type, d, s1);
2989 var_to_reg_flt(d, src, REG_FTMP1);
2990 M_DST(d, REG_SP, md->params[s3].regoff * 8);
2995 switch (iptr->opc) {
2997 disp = dseg_addaddress(cd, bte->fp);
2998 d = md->returntype.type;
3000 M_ALD(REG_ITMP3, REG_PV, disp); /* built-in-function pointer */
3001 M_JSR(REG_RA, REG_ITMP3);
3003 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3004 M_LDA(REG_PV, REG_RA, -disp);
3006 /* if op1 == true, we need to check for an exception */
3008 if (iptr->op1 == true) {
3009 M_BEQZ(REG_RESULT, 0);
3010 codegen_addxexceptionrefs(cd, mcodeptr);
3015 case ICMD_INVOKESPECIAL:
3016 M_BEQZ(rd->argintregs[0], 0);
3017 codegen_addxnullrefs(cd, mcodeptr);
3021 case ICMD_INVOKESTATIC:
3023 unresolved_method *um = iptr->target;
3025 disp = dseg_addaddress(cd, NULL);
3027 codegen_addpatchref(cd, mcodeptr,
3028 PATCHER_invokestatic_special, um, disp);
3030 if (opt_showdisassemble) {
3034 d = um->methodref->parseddesc.md->returntype.type;
3037 disp = dseg_addaddress(cd, lm->stubroutine);
3038 d = lm->parseddesc->returntype.type;
3041 M_ALD(REG_PV, REG_PV, disp); /* method pointer in pv */
3042 M_JSR(REG_RA, REG_PV);
3044 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3045 M_LDA(REG_PV, REG_RA, -disp);
3048 case ICMD_INVOKEVIRTUAL:
3049 gen_nullptr_check(rd->argintregs[0]);
3052 unresolved_method *um = iptr->target;
3054 codegen_addpatchref(cd, mcodeptr,
3055 PATCHER_invokevirtual, um, 0);
3057 if (opt_showdisassemble) {
3062 d = um->methodref->parseddesc.md->returntype.type;
3065 s1 = OFFSET(vftbl_t, table[0]) +
3066 sizeof(methodptr) * lm->vftblindex;
3067 d = lm->parseddesc->returntype.type;
3070 M_ALD(REG_METHODPTR, rd->argintregs[0],
3071 OFFSET(java_objectheader, vftbl));
3072 M_ALD(REG_PV, REG_METHODPTR, s1);
3073 M_JSR(REG_RA, REG_PV);
3075 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3076 M_LDA(REG_PV, REG_RA, -disp);
3079 case ICMD_INVOKEINTERFACE:
3080 gen_nullptr_check(rd->argintregs[0]);
3083 unresolved_method *um = iptr->target;
3085 codegen_addpatchref(cd, mcodeptr,
3086 PATCHER_invokeinterface, um, 0);
3088 if (opt_showdisassemble) {
3094 d = um->methodref->parseddesc.md->returntype.type;
3097 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3098 sizeof(methodptr*) * lm->class->index;
3100 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3102 d = lm->parseddesc->returntype.type;
3105 M_ALD(REG_METHODPTR, rd->argintregs[0],
3106 OFFSET(java_objectheader, vftbl));
3107 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3108 M_ALD(REG_PV, REG_METHODPTR, s2);
3109 M_JSR(REG_RA, REG_PV);
3111 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3112 M_LDA(REG_PV, REG_RA, -disp);
3116 /* d contains return type */
3118 if (d != TYPE_VOID) {
3119 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3120 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3121 M_INTMOVE(REG_RESULT, s1);
3122 store_reg_to_var_int(iptr->dst, s1);
3124 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3125 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3126 store_reg_to_var_flt(iptr->dst, s1);
3132 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3133 /* op1: 0 == array, 1 == class */
3134 /* val.a: (classinfo*) superclass */
3136 /* superclass is an interface:
3138 * OK if ((sub == NULL) ||
3139 * (sub->vftbl->interfacetablelength > super->index) &&
3140 * (sub->vftbl->interfacetable[-super->index] != NULL));
3142 * superclass is a class:
3144 * OK if ((sub == NULL) || (0
3145 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3146 * super->vftbl->diffvall));
3149 if (iptr->op1 == 1) {
3151 vftbl_t *supervftbl;
3154 super = (classinfo *) iptr->val.a;
3161 superindex = super->index;
3162 supervftbl = super->vftbl;
3165 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3166 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3169 var_to_reg_int(s1, src, REG_ITMP1);
3171 /* calculate interface checkcast code size */
3175 s2 += (opt_showdisassemble ? 2 : 0);
3177 /* calculate class checkcast code size */
3179 s3 = 10 /* 10 + (s1 == REG_ITMP1) */;
3181 s3 += (opt_showdisassemble ? 2 : 0);
3183 /* if class is not resolved, check which code to call */
3186 M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
3189 disp = dseg_adds4(cd, 0); /* super->flags */
3191 codegen_addpatchref(cd, mcodeptr,
3192 PATCHER_checkcast_instanceof_flags,
3193 (constant_classref *) iptr->target,
3196 if (opt_showdisassemble) {
3200 /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
3201 M_ILD(REG_ITMP2, REG_PV, disp);
3202 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3203 M_BEQZ(REG_ITMP2, 1 + s2 + 2);
3207 /* interface checkcast code */
3209 if (!super || super->flags & ACC_INTERFACE) {
3215 codegen_addpatchref(cd, mcodeptr,
3216 PATCHER_checkcast_instanceof_interface,
3217 (constant_classref *) iptr->target,
3220 if (opt_showdisassemble) {
3225 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3226 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3227 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3228 M_BLEZ(REG_ITMP3, 0);
3229 codegen_addxcastrefs(cd, mcodeptr);
3231 M_ALD(REG_ITMP3, REG_ITMP2,
3232 OFFSET(vftbl_t, interfacetable[0]) -
3233 superindex * sizeof(methodptr*));
3234 M_BEQZ(REG_ITMP3, 0);
3235 codegen_addxcastrefs(cd, mcodeptr);
3244 /* class checkcast code */
3246 if (!super || !(super->flags & ACC_INTERFACE)) {
3247 disp = dseg_addaddress(cd, (void *) supervftbl);
3254 codegen_addpatchref(cd, mcodeptr,
3255 PATCHER_checkcast_instanceof_class,
3256 (constant_classref *) iptr->target,
3259 if (opt_showdisassemble) {
3264 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3265 M_ALD(REG_ITMP3, REG_PV, disp);
3266 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3267 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3269 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3270 /* if (s1 != REG_ITMP1) { */
3271 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3272 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3273 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3274 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3276 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3278 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3279 M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3280 M_ALD(REG_ITMP3, REG_PV, disp);
3281 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3282 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3283 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3286 M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3287 M_BNEZ(REG_ITMP3, 0);
3288 codegen_addxcastrefs(cd, mcodeptr);
3291 d = reg_of_var(rd, iptr->dst, s1);
3294 var_to_reg_int(s1, src, rd->argintregs[0]);
3295 M_INTMOVE(s1, rd->argintregs[0]);
3297 disp = dseg_addaddress(cd, iptr->val.a);
3299 if (iptr->val.a == NULL) {
3300 codegen_addpatchref(cd, mcodeptr,
3301 PATCHER_builtin_arraycheckcast,
3302 (constant_classref *) iptr->target,
3305 if (opt_showdisassemble) {
3310 M_ALD(rd->argintregs[1], REG_PV, disp);
3311 disp = dseg_addaddress(cd, BUILTIN_arraycheckcast);
3312 M_ALD(REG_ITMP3, REG_PV, disp);
3313 M_JSR(REG_RA, REG_ITMP3);
3316 M_BEQZ(REG_RESULT, 0);
3317 codegen_addxcastrefs(cd, mcodeptr);
3320 var_to_reg_int(s1, src, REG_ITMP1);
3321 d = reg_of_var(rd, iptr->dst, s1);
3324 store_reg_to_var_int(iptr->dst, d);
3327 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3328 /* op1: 0 == array, 1 == class */
3329 /* val.a: (classinfo*) superclass */
3331 /* superclass is an interface:
3333 * return (sub != NULL) &&
3334 * (sub->vftbl->interfacetablelength > super->index) &&
3335 * (sub->vftbl->interfacetable[-super->index] != NULL);
3337 * superclass is a class:
3339 * return ((sub != NULL) && (0
3340 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3341 * super->vftbl->diffvall));
3346 vftbl_t *supervftbl;
3349 super = (classinfo *) iptr->val.a;
3356 superindex = super->index;
3357 supervftbl = super->vftbl;
3360 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3361 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3364 var_to_reg_int(s1, src, REG_ITMP1);
3365 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3367 M_MOV(s1, REG_ITMP1);
3371 /* calculate interface instanceof code size */
3375 s2 += (opt_showdisassemble ? 2 : 0);
3377 /* calculate class instanceof code size */
3381 s3 += (opt_showdisassemble ? 2 : 0);
3385 /* if class is not resolved, check which code to call */
3388 M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
3391 disp = dseg_adds4(cd, 0); /* super->flags */
3393 codegen_addpatchref(cd, mcodeptr,
3394 PATCHER_checkcast_instanceof_flags,
3395 (constant_classref *) iptr->target, disp);
3397 if (opt_showdisassemble) {
3401 /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
3402 M_ILD(REG_ITMP3, REG_PV, disp);
3403 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
3404 M_BEQZ(REG_ITMP3, 1 + s2 + 2);
3408 /* interface instanceof code */
3410 if (!super || (super->flags & ACC_INTERFACE)) {
3416 codegen_addpatchref(cd, mcodeptr,
3417 PATCHER_checkcast_instanceof_interface,
3418 (constant_classref *) iptr->target, 0);
3420 if (opt_showdisassemble) {
3425 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3426 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3427 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3428 M_BLEZ(REG_ITMP3, 3);
3430 M_ALD(REG_ITMP1, REG_ITMP1,
3431 OFFSET(vftbl_t, interfacetable[0]) -
3432 superindex * sizeof(methodptr*));
3433 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3441 /* class instanceof code */
3443 if (!super || !(super->flags & ACC_INTERFACE)) {
3444 disp = dseg_addaddress(cd, supervftbl);
3451 codegen_addpatchref(cd, mcodeptr,
3452 PATCHER_checkcast_instanceof_class,
3453 (constant_classref *) iptr->target,
3456 if (opt_showdisassemble) {
3461 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3462 M_ALD(REG_ITMP2, REG_PV, disp);
3463 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3464 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3466 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3467 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3468 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3469 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3470 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3472 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3473 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3476 store_reg_to_var_int(iptr->dst, d);
3480 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3481 /* op1 = dimension, val.a = array descriptor */
3483 /* check for negative sizes and copy sizes to stack if necessary */
3485 MCODECHECK((iptr->op1 << 1) + 64);
3487 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3488 /* copy SAVEDVAR sizes to stack */
3490 if (src->varkind != ARGVAR) {
3491 var_to_reg_int(s2, src, REG_ITMP1);
3492 M_LST(s2, REG_SP, s1 * 8);
3496 /* a0 = dimension count */
3498 ICONST(rd->argintregs[0], iptr->op1);
3500 /* is patcher function set? */
3503 disp = dseg_addaddress(cd, NULL);
3505 codegen_addpatchref(cd, mcodeptr,
3506 PATCHER_builtin_multianewarray,
3509 if (opt_showdisassemble) {
3514 disp = dseg_addaddress(cd, iptr->val.a);
3517 /* a1 = arraydescriptor */
3519 M_ALD(rd->argintregs[1], REG_PV, disp);
3521 /* a2 = pointer to dimensions = stack pointer */
3523 M_INTMOVE(REG_SP, rd->argintregs[2]);
3525 disp = dseg_addaddress(cd, BUILTIN_multianewarray);
3526 M_ALD(REG_ITMP3, REG_PV, disp);
3527 M_JSR(REG_RA, REG_ITMP3);
3530 /* check for exception before result assignment */
3532 M_BEQZ(REG_RESULT, 0);
3533 codegen_addxexceptionrefs(cd, mcodeptr);
3536 d = reg_of_var(rd, iptr->dst, REG_RESULT);
3537 M_INTMOVE(REG_RESULT, d);
3538 store_reg_to_var_int(iptr->dst, d);
3542 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3546 } /* for instruction */
3548 /* copy values to interface registers */
3550 src = bptr->outstack;
3551 len = bptr->outdepth;
3558 if ((src->varkind != STACKVAR)) {
3560 if (IS_FLT_DBL_TYPE(s2)) {
3561 var_to_reg_flt(s1, src, REG_FTMP1);
3562 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3563 M_TFLTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3566 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3570 var_to_reg_int(s1, src, REG_ITMP1);
3571 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3572 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3575 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3582 /* At the end of a basic block we may have to append some nops,
3583 because the patcher stub calling code might be longer than the
3584 actual instruction. So codepatching does not change the
3585 following block unintentionally. */
3587 if ((u1 *) mcodeptr < cd->lastmcodeptr) {
3588 while ((u1 *) mcodeptr < cd->lastmcodeptr) {
3593 } /* if (bptr -> flags >= BBREACHED) */
3594 } /* for basic block */
3596 codegen_createlinenumbertable(cd);
3602 /* generate ArithmeticException stubs */
3606 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3607 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3609 (u1 *) mcodeptr - cd->mcodebase);
3613 if (xcodeptr != NULL) {
3614 M_BR(xcodeptr - mcodeptr);
3615 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3618 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3620 xcodeptr = mcodeptr;
3622 M_MOV(REG_PV, rd->argintregs[0]);
3623 M_MOV(REG_SP, rd->argintregs[1]);
3625 if (m->isleafmethod)
3626 M_MOV(REG_RA, rd->argintregs[2]);
3628 M_ALD(rd->argintregs[2],
3629 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3631 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3633 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3634 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3636 if (m->isleafmethod)
3637 M_AST(REG_RA, REG_SP, 1 * 8);
3639 a = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
3640 M_ALD(REG_ITMP3, REG_PV, a);
3641 M_JSR(REG_RA, REG_ITMP3);
3643 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3645 if (m->isleafmethod)
3646 M_ALD(REG_RA, REG_SP, 1 * 8);
3648 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3649 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3651 a = dseg_addaddress(cd, asm_handle_exception);
3652 M_ALD(REG_ITMP3, REG_PV, a);
3658 /* generate ArrayIndexOutOfBoundsException stubs */
3662 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3663 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3665 (u1 *) mcodeptr - cd->mcodebase);
3669 /* move index register into REG_ITMP1 */
3671 M_MOV(bref->reg, REG_ITMP1);
3672 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3674 if (xcodeptr != NULL) {
3675 M_BR(xcodeptr - mcodeptr);
3679 xcodeptr = mcodeptr;
3681 M_MOV(REG_PV, rd->argintregs[0]);
3682 M_MOV(REG_SP, rd->argintregs[1]);
3684 if (m->isleafmethod)
3685 M_MOV(REG_RA, rd->argintregs[2]);
3687 M_ALD(rd->argintregs[2],
3688 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3690 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3691 M_MOV(REG_ITMP1, rd->argintregs[4]);
3693 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3694 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3696 if (m->isleafmethod)
3697 M_AST(REG_RA, REG_SP, 1 * 8);
3699 a = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
3700 M_ALD(REG_ITMP3, REG_PV, a);
3701 M_JSR(REG_RA, REG_ITMP3);
3703 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3705 if (m->isleafmethod)
3706 M_ALD(REG_RA, REG_SP, 1 * 8);
3708 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3709 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3711 a = dseg_addaddress(cd, asm_handle_exception);
3712 M_ALD(REG_ITMP3, REG_PV, a);
3718 /* generate ArrayStoreException stubs */
3722 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
3723 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3725 (u1 *) mcodeptr - cd->mcodebase);
3729 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3731 if (xcodeptr != NULL) {
3732 M_BR(xcodeptr - mcodeptr);
3736 xcodeptr = mcodeptr;
3738 M_MOV(REG_PV, rd->argintregs[0]);
3739 M_MOV(REG_SP, rd->argintregs[1]);
3740 M_ALD(rd->argintregs[2],
3741 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3742 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3744 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3745 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3747 a = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
3748 M_ALD(REG_ITMP3, REG_PV, a);
3749 M_JSR(REG_RA, REG_ITMP3);
3751 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3753 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3754 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3756 a = dseg_addaddress(cd, asm_handle_exception);
3757 M_ALD(REG_ITMP3, REG_PV, a);
3763 /* generate ClassCastException stubs */
3767 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3768 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3770 (u1 *) mcodeptr - cd->mcodebase);
3774 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3776 if (xcodeptr != NULL) {
3777 M_BR(xcodeptr - mcodeptr);
3781 xcodeptr = mcodeptr;
3783 M_MOV(REG_PV, rd->argintregs[0]);
3784 M_MOV(REG_SP, rd->argintregs[1]);
3786 if (m->isleafmethod)
3787 M_MOV(REG_RA, rd->argintregs[2]);
3789 M_ALD(rd->argintregs[2],
3790 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3792 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3794 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3795 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3797 if (m->isleafmethod)
3798 M_AST(REG_RA, REG_SP, 1 * 8);
3800 a = dseg_addaddress(cd, stacktrace_inline_classcastexception);
3801 M_ALD(REG_ITMP3, REG_PV, a);
3802 M_JSR(REG_RA, REG_ITMP3);
3804 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3806 if (m->isleafmethod)
3807 M_ALD(REG_RA, REG_SP, 1 * 8);
3809 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3810 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3812 a = dseg_addaddress(cd, asm_handle_exception);
3813 M_ALD(REG_ITMP3, REG_PV, a);
3819 /* generate NullPointerException stubs */
3823 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3824 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3826 (u1 *) mcodeptr - cd->mcodebase);
3830 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3832 if (xcodeptr != NULL) {
3833 M_BR(xcodeptr - mcodeptr);
3837 xcodeptr = mcodeptr;
3839 M_MOV(REG_PV, rd->argintregs[0]);
3840 M_MOV(REG_SP, rd->argintregs[1]);
3842 if (m->isleafmethod)
3843 M_MOV(REG_RA, rd->argintregs[2]);
3845 M_ALD(rd->argintregs[2],
3846 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3848 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3850 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3851 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3853 if (m->isleafmethod)
3854 M_AST(REG_RA, REG_SP, 1 * 8);
3856 a = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
3857 M_ALD(REG_ITMP3, REG_PV, a);
3858 M_JSR(REG_RA, REG_ITMP3);
3860 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3862 if (m->isleafmethod)
3863 M_ALD(REG_RA, REG_SP, 1 * 8);
3865 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3866 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3868 a = dseg_addaddress(cd, asm_handle_exception);
3869 M_ALD(REG_ITMP3, REG_PV, a);
3875 /* generate exception check stubs */
3879 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3880 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3882 (u1 *) mcodeptr - cd->mcodebase);
3886 if (xcodeptr != NULL) {
3887 M_BR(xcodeptr - mcodeptr);
3888 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3891 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3893 xcodeptr = mcodeptr;
3895 M_MOV(REG_PV, rd->argintregs[0]);
3896 M_MOV(REG_SP, rd->argintregs[1]);
3897 M_ALD(rd->argintregs[2],
3898 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3899 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3901 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3902 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3904 a = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
3905 M_ALD(REG_ITMP3, REG_PV, a);
3906 M_JSR(REG_RA, REG_ITMP3);
3908 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3910 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3911 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3913 a = dseg_addaddress(cd, asm_handle_exception);
3914 M_ALD(REG_ITMP3, REG_PV, a);
3920 /* generate patcher stub call code */
3927 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3928 /* check code segment size */
3932 /* Get machine code which is patched back in later. The call is */
3933 /* 2 instruction words long. */
3935 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3937 /* We need to split this, because an unaligned 8 byte read causes */
3940 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3942 /* patch in the call to call the following code (done at compile */
3945 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3946 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3948 disp = (s4) (tmpmcodeptr - (xcodeptr + 1));
3950 if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) {
3952 new_internalerror("Jump offset is out of range: %d > +/-%d",
3960 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3962 /* create stack frame */
3964 M_ASUB_IMM(REG_SP, 6 * 8, REG_SP);
3966 /* calculate return address and move it onto the stack */
3968 M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
3969 M_AST(REG_ITMP3, REG_SP, 5 * 8);
3971 /* move pointer to java_objectheader onto stack */
3973 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3974 /* create a virtual java_objectheader */
3976 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3977 disp = dseg_addaddress(cd, NULL); /* vftbl */
3979 M_LDA(REG_ITMP3, REG_PV, disp);
3980 M_AST(REG_ITMP3, REG_SP, 4 * 8);
3985 /* move machine code onto stack */
3987 disp = dseg_adds8(cd, mcode);
3988 M_LLD(REG_ITMP3, REG_PV, disp);
3989 M_LST(REG_ITMP3, REG_SP, 3 * 8);
3991 /* move class/method/field reference onto stack */
3993 disp = dseg_addaddress(cd, pref->ref);
3994 M_ALD(REG_ITMP3, REG_PV, disp);
3995 M_AST(REG_ITMP3, REG_SP, 2 * 8);
3997 /* move data segment displacement onto stack */
3999 disp = dseg_adds4(cd, pref->disp);
4000 M_ILD(REG_ITMP3, REG_PV, disp);
4001 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4003 /* move patcher function pointer onto stack */
4005 disp = dseg_addaddress(cd, pref->patcher);
4006 M_ALD(REG_ITMP3, REG_PV, disp);
4007 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4009 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4010 M_ALD(REG_ITMP3, REG_PV, disp);
4017 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4019 docacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4021 /* everything's ok */
4027 /* createcompilerstub **********************************************************
4029 Creates a stub routine which calls the compiler.
4031 *******************************************************************************/
4033 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
4034 #define COMPILERSTUB_CODESIZE 4 * 4
4036 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4039 u1 *createcompilerstub(methodinfo *m)
4041 ptrint *s; /* memory to hold the stub */
4042 s4 *mcodeptr; /* code generation pointer */
4044 s = (ptrint *) CNEW(u1, COMPILERSTUB_SIZE);
4047 s[1] = (ptrint) asm_call_jit_compiler;
4049 mcodeptr = (s4 *) (s + 2);
4051 M_ALD(REG_ITMP1, REG_PV, -2 * SIZEOF_VOID_P); /* method pointer */
4052 M_ALD(REG_PV, REG_PV, -1 * SIZEOF_VOID_P); /* pointer to compiler */
4056 (void) docacheflush((void *) s, (char *) mcodeptr - (char *) s);
4058 #if defined(STATISTICS)
4060 count_cstub_len += COMPILERSTUB_SIZE;
4063 return (((u1 *) s) + COMPILERSTUB_DATASIZE);
4067 /* createnativestub ************************************************************
4069 Creates a stub routine which calls a native method.
4071 *******************************************************************************/
4073 u1 *createnativestub(functionptr f, methodinfo *m, codegendata *cd,
4074 registerdata *rd, methoddesc *nmd)
4076 s4 *mcodeptr; /* code generation pointer */
4077 s4 stackframesize; /* size of stackframe if needed */
4080 s4 i, j; /* count variables */
4083 s4 funcdisp; /* displacement of the function */
4086 /* initialize variables */
4089 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4092 /* calculate stack frame size */
4095 1 + /* return address */
4096 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4097 sizeof(localref_table) / SIZEOF_VOID_P +
4098 md->paramcount + /* for saving arguments over calls */
4099 1 + /* for saving return address */
4103 /* create method header */
4105 #if SIZEOF_VOID_P == 4
4106 (void) dseg_addaddress(cd, m); /* MethodPointer */
4108 (void) dseg_addaddress(cd, m); /* MethodPointer */
4109 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4110 (void) dseg_adds4(cd, 0); /* IsSync */
4111 (void) dseg_adds4(cd, 0); /* IsLeaf */
4112 (void) dseg_adds4(cd, 0); /* IntSave */
4113 (void) dseg_adds4(cd, 0); /* FltSave */
4114 (void) dseg_addlinenumbertablesize(cd);
4115 (void) dseg_adds4(cd, 0); /* ExTableSize */
4118 /* initialize mcode variables */
4120 mcodeptr = (s4 *) cd->mcodebase;
4121 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
4124 /* generate stub code */
4126 M_LDA(REG_SP, REG_SP, -stackframesize * 8); /* build up stackframe */
4127 M_AST(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* store ra */
4130 /* call trace function */
4133 M_LDA(REG_SP, REG_SP, -(1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4135 /* save integer argument registers */
4137 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4138 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4139 M_LST(rd->argintregs[i], REG_SP, (1 + i) * 8);
4141 /* save and copy float arguments into integer registers */
4143 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4144 t = md->paramtypes[i].type;
4146 if (IS_FLT_DBL_TYPE(t)) {
4147 if (IS_2_WORD_TYPE(t)) {
4148 M_DST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4149 M_LLD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4151 M_FST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4152 M_ILD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4157 disp = dseg_addaddress(cd, m);
4158 M_ALD(REG_ITMP1, REG_PV, disp);
4159 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4160 disp = dseg_addaddress(cd, builtin_trace_args);
4161 M_ALD(REG_ITMP3, REG_PV, disp);
4162 M_JSR(REG_RA, REG_ITMP3);
4165 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4166 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4167 M_LLD(rd->argintregs[i], REG_SP, (1 + i) * 8);
4169 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4170 t = md->paramtypes[i].type;
4172 if (IS_FLT_DBL_TYPE(t)) {
4173 if (IS_2_WORD_TYPE(t)) {
4174 M_DLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4176 M_FLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4181 M_LDA(REG_SP, REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4185 /* get function address (this must happen before the stackframeinfo) */
4187 funcdisp = dseg_addaddress(cd, f);
4189 #if !defined(ENABLE_STATICVM)
4191 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m, funcdisp);
4193 if (opt_showdisassemble) {
4199 /* save integer and float argument registers */
4201 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4202 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4203 M_LST(rd->argintregs[i], REG_SP, j * 8);
4208 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4209 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4210 M_DST(rd->argfltregs[i], REG_SP, j * 8);
4215 /* prepare data structures for native function call */
4217 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4218 M_MOV(REG_PV, rd->argintregs[1]);
4219 M_AADD_IMM(REG_SP, stackframesize * 8, rd->argintregs[2]);
4220 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8 - SIZEOF_VOID_P);
4221 disp = dseg_addaddress(cd, codegen_start_native_call);
4222 M_ALD(REG_ITMP3, REG_PV, disp);
4223 M_JSR(REG_RA, REG_ITMP3);
4224 M_NOP; /* XXX fill me! */
4226 /* restore integer and float argument registers */
4228 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4229 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4230 M_LLD(rd->argintregs[i], REG_SP, j * 8);
4235 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4236 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4237 M_DLD(rd->argfltregs[i], REG_SP, j * 8);
4242 /* copy or spill arguments to new locations */
4244 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4245 t = md->paramtypes[i].type;
4247 if (IS_INT_LNG_TYPE(t)) {
4248 if (!md->params[i].inmemory) {
4249 s1 = rd->argintregs[md->params[i].regoff];
4251 if (!nmd->params[j].inmemory) {
4252 s2 = rd->argintregs[nmd->params[j].regoff];
4255 s2 = nmd->params[j].regoff;
4256 M_AST(s1, REG_SP, s2 * 8);
4260 s1 = md->params[i].regoff + stackframesize;
4261 s2 = nmd->params[j].regoff;
4262 M_ALD(REG_ITMP1, REG_SP, s1 * 8);
4263 M_AST(REG_ITMP1, REG_SP, s2 * 8);
4267 if (!md->params[i].inmemory) {
4268 s1 = rd->argfltregs[md->params[i].regoff];
4270 if (!nmd->params[j].inmemory) {
4271 s2 = rd->argfltregs[nmd->params[j].regoff];
4272 M_TFLTMOVE(t, s1, s2);
4274 s2 = nmd->params[j].regoff;
4275 if (IS_2_WORD_TYPE(t))
4276 M_DST(s1, REG_SP, s2 * 8);
4278 M_FST(s1, REG_SP, s2 * 8);
4282 s1 = md->params[i].regoff + stackframesize;
4283 s2 = nmd->params[j].regoff;
4284 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4285 if (IS_2_WORD_TYPE(t))
4286 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4288 M_FST(REG_FTMP1, REG_SP, s2 * 8);
4293 /* put class into second argument register */
4295 if (m->flags & ACC_STATIC) {
4296 disp = dseg_addaddress(cd, m->class);
4297 M_ALD(rd->argintregs[1], REG_PV, disp);
4300 /* put env into first argument register */
4302 disp = dseg_addaddress(cd, &env);
4303 M_ALD(rd->argintregs[0], REG_PV, disp);
4305 /* do the native function call */
4307 M_ALD(REG_ITMP3, REG_PV, funcdisp); /* load adress of native method */
4308 M_JSR(REG_RA, REG_ITMP3); /* call native method */
4309 M_NOP; /* delay slot */
4311 /* save return value */
4313 if (IS_INT_LNG_TYPE(md->returntype.type))
4314 M_LST(REG_RESULT, REG_SP, 0 * 8);
4316 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4318 /* remove native stackframe info */
4320 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4321 disp = dseg_addaddress(cd, codegen_finish_native_call);
4322 M_ALD(REG_ITMP3, REG_PV, disp);
4323 M_JSR(REG_RA, REG_ITMP3);
4324 M_NOP; /* XXX fill me! */
4326 /* call finished trace function */
4329 if (IS_INT_LNG_TYPE(md->returntype.type))
4330 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4332 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4334 disp = dseg_addaddress(cd, m);
4335 M_ALD(rd->argintregs[0], REG_PV, disp);
4337 M_MOV(REG_RESULT, rd->argintregs[1]);
4338 M_DMFC1(REG_ITMP1, REG_FRESULT);
4339 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4340 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4342 disp = dseg_addaddress(cd, builtin_displaymethodstop);
4343 M_ALD(REG_ITMP3, REG_PV, disp);
4344 M_JSR(REG_RA, REG_ITMP3);
4348 /* check for exception */
4350 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4351 disp = dseg_addaddress(cd, builtin_get_exceptionptrptr);
4352 M_ALD(REG_ITMP3, REG_PV, disp);
4353 M_JSR(REG_RA, REG_ITMP3);
4355 M_MOV(REG_RESULT, REG_ITMP3);
4357 disp = dseg_addaddress(cd, &_exceptionptr);
4358 M_ALD(REG_ITMP3, REG_PV, disp); /* get address of exceptionptr */
4360 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4362 M_ALD(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* load ra */
4364 /* restore return value */
4366 if (IS_INT_LNG_TYPE(md->returntype.type))
4367 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4369 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4371 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
4372 M_LDA(REG_SP, REG_SP, stackframesize * 8);/* remove stackframe, DELAY SLOT*/
4374 M_RET(REG_RA); /* return to caller */
4375 M_NOP; /* DELAY SLOT */
4377 /* handle exception */
4379 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4381 disp = dseg_addaddress(cd, asm_handle_nat_exception);
4382 M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */
4383 M_JMP(REG_ITMP3); /* jump to asm exception handler */
4384 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4387 /* generate static stub call code */
4395 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4396 /* Get machine code which is patched back in later. The call is */
4397 /* 2 instruction words long. */
4399 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4401 /* We need to split this, because an unaligned 8 byte read causes */
4404 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
4406 /* patch in the call to call the following code (done at compile */
4409 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4410 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4412 M_BRS(tmpmcodeptr - (xcodeptr + 1));
4413 M_NOP; /* branch delay slot */
4415 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4417 /* create stack frame */
4419 M_LSUB_IMM(REG_SP, 6 * 8, REG_SP);
4421 /* move return address onto stack */
4423 M_AST(REG_RA, REG_SP, 5 * 8);
4425 /* move pointer to java_objectheader onto stack */
4427 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4428 /* order reversed because of data segment layout */
4430 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4431 disp = dseg_addaddress(cd, NULL); /* vftbl */
4433 M_LDA(REG_ITMP3, REG_PV, disp);
4434 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4436 M_AST(REG_ZERO, REG_SP, 4 * 8);
4439 /* move machine code onto stack */
4441 disp = dseg_adds8(cd, mcode);
4442 M_LLD(REG_ITMP3, REG_PV, disp);
4443 M_LST(REG_ITMP3, REG_SP, 3 * 8);
4445 /* move class/method/field reference onto stack */
4447 disp = dseg_addaddress(cd, pref->ref);
4448 M_ALD(REG_ITMP3, REG_PV, disp);
4449 M_AST(REG_ITMP3, REG_SP, 2 * 8);
4451 /* move data segment displacement onto stack */
4453 disp = dseg_adds4(cd, pref->disp);
4454 M_ILD(REG_ITMP3, REG_PV, disp);
4455 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4457 /* move patcher function pointer onto stack */
4459 disp = dseg_addaddress(cd, pref->patcher);
4460 M_ALD(REG_ITMP3, REG_PV, disp);
4461 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4463 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4464 M_ALD(REG_ITMP3, REG_PV, disp);
4470 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4472 docacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4474 return m->entrypoint;
4479 * These are local overrides for various environment variables in Emacs.
4480 * Please do not remove this and leave it at the end of the file, where
4481 * Emacs will automagically detect them.
4482 * ---------------------------------------------------------------------
4485 * indent-tabs-mode: t