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 3761 2005-11-23 12:31:43Z 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"
59 #include "vm/stringlocal.h"
60 #include "vm/jit/asmpart.h"
61 #include "vm/jit/codegen.inc"
62 #include "vm/jit/jit.h"
65 # include "vm/jit/lsra.h"
66 # include "vm/jit/lsra.inc"
69 #include "vm/jit/patcher.h"
70 #include "vm/jit/reg.h"
71 #include "vm/jit/reg.inc"
74 /* codegen *********************************************************************
76 Generates machine code.
78 *******************************************************************************/
80 bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
82 s4 len, s1, s2, s3, d, disp;
92 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
93 builtintable_entry *bte;
100 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
102 /* space to save used callee saved registers */
104 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
105 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
107 parentargs_base = rd->memuse + savedregs_num;
109 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
110 if (checksync && (m->flags & ACC_SYNCHRONIZED))
114 /* adjust frame size for 16 byte alignment */
116 if (parentargs_base & 1)
119 /* create method header */
121 #if SIZEOF_VOID_P == 4
122 (void) dseg_addaddress(cd, m); /* Filler */
124 (void) dseg_addaddress(cd, m); /* MethodPointer */
125 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
127 #if defined(USE_THREADS)
128 /* IsSync contains the offset relative to the stack pointer for the
129 argument of monitor_exit used in the exception handler. Since the
130 offset could be zero and give a wrong meaning of the flag it is
134 if (checksync && (m->flags & ACC_SYNCHRONIZED))
135 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
138 (void) dseg_adds4(cd, 0); /* IsSync */
140 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
141 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
142 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
143 dseg_addlinenumbertablesize(cd);
144 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
146 /* create exception table */
148 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
149 dseg_addtarget(cd, ex->start);
150 dseg_addtarget(cd, ex->end);
151 dseg_addtarget(cd, ex->handler);
152 (void) dseg_addaddress(cd, ex->catchtype.cls);
155 /* initialize mcode variables */
157 mcodeptr = (s4 *) cd->mcodebase;
158 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
159 MCODECHECK(128 + m->paramcount);
161 /* initialize the last patcher pointer */
163 cd->lastmcodeptr = (u1 *) mcodeptr;
165 /* create stack frame (if necessary) */
168 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
170 /* save return address and used callee saved registers */
173 if (!m->isleafmethod) {
174 p--; M_AST(REG_RA, REG_SP, p * 8);
176 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
177 p--; M_AST(rd->savintregs[i], REG_SP, p * 8);
179 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
180 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
183 /* take arguments out of register or stack frame */
187 for (p = 0, l = 0; p < md->paramcount; p++) {
188 t = md->paramtypes[p].type;
189 var = &(rd->locals[l][t]);
191 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
195 s1 = md->params[p].regoff;
196 if (IS_INT_LNG_TYPE(t)) { /* integer args */
197 if (!md->params[p].inmemory) { /* register arguments */
198 s2 = rd->argintregs[s1];
199 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
200 M_INTMOVE(s2, var->regoff);
201 } else { /* reg arg -> spilled */
202 M_LST(s2, REG_SP, var->regoff * 8);
205 } else { /* stack arguments */
206 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
207 M_LLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
208 } else { /* stack arg -> spilled */
209 var->regoff = parentargs_base + s1;
213 } else { /* floating args */
214 if (!md->params[p].inmemory) { /* register arguments */
215 s2 = rd->argfltregs[s1];
216 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
217 M_TFLTMOVE(var->type, s2, var->regoff);
218 } else { /* reg arg -> spilled */
219 M_DST(s2, REG_SP, var->regoff * 8);
222 } else { /* stack arguments */
223 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
224 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
225 } else { /* stack-arg -> spilled */
226 var->regoff = parentargs_base + s1;
232 /* call monitorenter function */
234 #if defined(USE_THREADS)
235 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
236 /* stack offset for monitor argument */
241 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
243 for (p = 0; p < INT_ARG_CNT; p++)
244 M_LST(rd->argintregs[p], REG_SP, p * 8);
246 for (p = 0; p < FLT_ARG_CNT; p++)
247 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
249 s1 += INT_ARG_CNT + FLT_ARG_CNT;
252 /* decide which monitor enter function to call */
254 if (m->flags & ACC_STATIC) {
255 p = dseg_addaddress(cd, m->class);
256 M_ALD(REG_ITMP1, REG_PV, p);
257 M_AST(REG_ITMP1, REG_SP, s1 * 8);
258 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
259 M_ALD(REG_ITMP3, REG_PV, p);
260 M_JSR(REG_RA, REG_ITMP3);
261 M_INTMOVE(REG_ITMP1, rd->argintregs[0]); /* branch delay */
264 M_BEQZ(rd->argintregs[0], 0);
265 codegen_addxnullrefs(cd, mcodeptr);
266 p = dseg_addaddress(cd, BUILTIN_monitorenter);
267 M_ALD(REG_ITMP3, REG_PV, p);
268 M_JSR(REG_RA, REG_ITMP3);
269 M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* br delay */
273 for (p = 0; p < INT_ARG_CNT; p++)
274 M_LLD(rd->argintregs[p], REG_SP, p * 8);
276 for (p = 0; p < FLT_ARG_CNT; p++)
277 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
280 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
285 /* copy argument registers to stack and call trace function */
288 M_LDA(REG_SP, REG_SP, -(2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
289 M_AST(REG_RA, REG_SP, 1 * 8);
291 /* save integer argument registers */
293 for (p = 0; p < md->paramcount && p < INT_ARG_CNT; p++)
294 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
296 /* save and copy float arguments into integer registers */
298 for (p = 0; p < md->paramcount && p < FLT_ARG_CNT; p++) {
299 t = md->paramtypes[p].type;
301 if (IS_FLT_DBL_TYPE(t)) {
302 if (IS_2_WORD_TYPE(t)) {
303 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
304 M_LLD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
307 M_FST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
308 M_ILD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
312 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
316 /* save temporary registers for leaf methods */
318 if (m->isleafmethod) {
319 for (p = 0; p < INT_TMP_CNT; p++)
320 M_LST(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
322 for (p = 0; p < FLT_TMP_CNT; p++)
323 M_DST(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
326 p = dseg_addaddress(cd, m);
327 M_ALD(REG_ITMP1, REG_PV, p);
328 M_AST(REG_ITMP1, REG_SP, 0 * 8);
329 disp = dseg_addaddress(cd, (void *) builtin_trace_args);
330 M_ALD(REG_ITMP3, REG_PV, disp);
331 M_JSR(REG_RA, REG_ITMP3);
334 M_ALD(REG_RA, REG_SP, 1 * 8);
336 /* restore integer argument registers */
338 for (p = 0; p < md->paramcount && p < INT_ARG_CNT; p++)
339 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
341 /* restore float argument registers */
343 for (p = 0; p < md->paramcount && p < FLT_ARG_CNT; p++) {
344 t = md->paramtypes[p].type;
346 if (IS_FLT_DBL_TYPE(t)) {
347 if (IS_2_WORD_TYPE(t)) {
348 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
351 M_FLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
355 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
359 /* restore temporary registers for leaf methods */
361 if (m->isleafmethod) {
362 for (p = 0; p < INT_TMP_CNT; p++)
363 M_LLD(rd->tmpintregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
365 for (p = 0; p < FLT_TMP_CNT; p++)
366 M_DLD(rd->tmpfltregs[p], REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
369 M_LDA(REG_SP, REG_SP, (2 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT) * 8);
374 /* end of header generation */
376 /* walk through all basic blocks */
378 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
380 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
382 if (bptr->flags >= BBREACHED) {
384 /* branch resolving */
387 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
388 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
394 /* copy interface registers to their destination */
401 while (src != NULL) {
403 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
404 /* d = reg_of_var(m, src, REG_ITMP1); */
405 if (!(src->flags & INMEMORY))
409 M_INTMOVE(REG_ITMP1, d);
410 store_reg_to_var_int(src, d);
416 while (src != NULL) {
418 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
419 d = reg_of_var(rd, src, REG_ITMP1);
420 M_INTMOVE(REG_ITMP1, d);
421 store_reg_to_var_int(src, d);
424 d = reg_of_var(rd, src, REG_IFTMP);
425 if ((src->varkind != STACKVAR)) {
427 if (IS_FLT_DBL_TYPE(s2)) {
428 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
429 s1 = rd->interfaces[len][s2].regoff;
430 M_TFLTMOVE(s2, s1, d);
433 M_DLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
435 store_reg_to_var_flt(src, d);
438 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
439 s1 = rd->interfaces[len][s2].regoff;
443 M_LLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
445 store_reg_to_var_int(src, d);
454 /* walk through all instructions */
460 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
461 if (iptr->line != currentline) {
462 dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
463 currentline = iptr->line;
466 MCODECHECK(64); /* an instruction usually needs < 64 words */
470 case ICMD_NOP: /* ... ==> ... */
473 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
475 var_to_reg_int(s1, src, REG_ITMP1);
477 codegen_addxnullrefs(cd, mcodeptr);
481 /* constant operations ************************************************/
483 case ICMD_ICONST: /* ... ==> ..., constant */
484 /* op1 = 0, val.i = constant */
486 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
487 ICONST(d, iptr->val.i);
488 store_reg_to_var_int(iptr->dst, d);
491 case ICMD_LCONST: /* ... ==> ..., constant */
492 /* op1 = 0, val.l = constant */
494 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
495 LCONST(d, iptr->val.l);
496 store_reg_to_var_int(iptr->dst, d);
499 case ICMD_FCONST: /* ... ==> ..., constant */
500 /* op1 = 0, val.f = constant */
502 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
503 disp = dseg_addfloat(cd, iptr->val.f);
504 M_FLD(d, REG_PV, disp);
505 store_reg_to_var_flt(iptr->dst, d);
508 case ICMD_DCONST: /* ... ==> ..., constant */
509 /* op1 = 0, val.d = constant */
511 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
512 disp = dseg_adddouble(cd, iptr->val.d);
513 M_DLD(d, REG_PV, disp);
514 store_reg_to_var_flt (iptr->dst, d);
517 case ICMD_ACONST: /* ... ==> ..., constant */
518 /* op1 = 0, val.a = constant */
520 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
522 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
523 disp = dseg_addaddress(cd, iptr->val.a);
525 codegen_addpatchref(cd, mcodeptr,
527 (unresolved_class *) iptr->target, disp);
529 if (opt_showdisassemble) {
533 M_ALD(d, REG_PV, disp);
536 if (iptr->val.a == NULL) {
537 M_INTMOVE(REG_ZERO, d);
539 disp = dseg_addaddress(cd, iptr->val.a);
540 M_ALD(d, REG_PV, disp);
543 store_reg_to_var_int(iptr->dst, d);
547 /* load/store operations **********************************************/
549 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
550 case ICMD_LLOAD: /* op1 = local variable */
553 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
554 if ((iptr->dst->varkind == LOCALVAR) &&
555 (iptr->dst->varnum == iptr->op1))
557 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
558 if (var->flags & INMEMORY) {
559 M_LLD(d, REG_SP, 8 * var->regoff);
561 M_INTMOVE(var->regoff,d);
563 store_reg_to_var_int(iptr->dst, d);
566 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
567 case ICMD_DLOAD: /* op1 = local variable */
569 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
570 if ((iptr->dst->varkind == LOCALVAR) &&
571 (iptr->dst->varnum == iptr->op1))
573 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
575 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
576 if (var->flags & INMEMORY) {
577 M_CCFLD(var->type, t2, d, REG_SP, 8 * var->regoff);
579 M_CCFLTMOVE(var->type, t2, var->regoff, d);
582 store_reg_to_var_flt(iptr->dst, d);
586 case ICMD_ISTORE: /* ..., value ==> ... */
587 case ICMD_LSTORE: /* op1 = local variable */
590 if ((src->varkind == LOCALVAR) &&
591 (src->varnum == iptr->op1))
593 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
594 if (var->flags & INMEMORY) {
595 var_to_reg_int(s1, src, REG_ITMP1);
596 M_LST(s1, REG_SP, 8 * var->regoff);
599 var_to_reg_int(s1, src, var->regoff);
600 M_INTMOVE(s1, var->regoff);
604 case ICMD_FSTORE: /* ..., value ==> ... */
605 case ICMD_DSTORE: /* op1 = local variable */
607 if ((src->varkind == LOCALVAR) &&
608 (src->varnum == iptr->op1))
610 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
612 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
613 if (var->flags & INMEMORY) {
614 var_to_reg_flt(s1, src, REG_FTMP1);
615 M_CCFST(t1, var->type, s1, REG_SP, 8 * var->regoff);
618 var_to_reg_flt(s1, src, var->regoff);
619 M_CCFLTMOVE(t1, var->type, s1, var->regoff);
625 /* pop/dup/swap operations ********************************************/
627 /* attention: double and longs are only one entry in CACAO ICMDs */
629 case ICMD_POP: /* ..., value ==> ... */
630 case ICMD_POP2: /* ..., value, value ==> ... */
633 case ICMD_DUP: /* ..., a ==> ..., a, a */
634 M_COPY(src, iptr->dst);
637 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
639 M_COPY(src, iptr->dst);
640 M_COPY(src->prev, iptr->dst->prev);
641 M_COPY(iptr->dst, iptr->dst->prev->prev);
644 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
646 M_COPY(src, iptr->dst);
647 M_COPY(src->prev, iptr->dst->prev);
648 M_COPY(src->prev->prev, iptr->dst->prev->prev);
649 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
652 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
654 M_COPY(src, iptr->dst);
655 M_COPY(src->prev, iptr->dst->prev);
658 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
660 M_COPY(src, iptr->dst);
661 M_COPY(src->prev, iptr->dst->prev);
662 M_COPY(src->prev->prev, iptr->dst->prev->prev);
663 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
664 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
667 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
669 M_COPY(src, iptr->dst);
670 M_COPY(src->prev, iptr->dst->prev);
671 M_COPY(src->prev->prev, iptr->dst->prev->prev);
672 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
673 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
674 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
677 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
679 M_COPY(src, iptr->dst->prev);
680 M_COPY(src->prev, iptr->dst);
684 /* integer operations *************************************************/
686 case ICMD_INEG: /* ..., value ==> ..., - value */
688 var_to_reg_int(s1, src, REG_ITMP1);
689 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
690 M_ISUB(REG_ZERO, s1, d);
691 store_reg_to_var_int(iptr->dst, d);
694 case ICMD_LNEG: /* ..., value ==> ..., - value */
696 var_to_reg_int(s1, src, REG_ITMP1);
697 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
698 M_LSUB(REG_ZERO, s1, d);
699 store_reg_to_var_int(iptr->dst, d);
702 case ICMD_I2L: /* ..., value ==> ..., value */
704 var_to_reg_int(s1, src, REG_ITMP1);
705 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
707 store_reg_to_var_int(iptr->dst, d);
710 case ICMD_L2I: /* ..., value ==> ..., value */
712 var_to_reg_int(s1, src, REG_ITMP1);
713 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
714 M_ISLL_IMM(s1, 0, d );
715 store_reg_to_var_int(iptr->dst, d);
718 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
720 var_to_reg_int(s1, src, REG_ITMP1);
721 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
722 M_LSLL_IMM(s1, 56, d);
723 M_LSRA_IMM( d, 56, d);
724 store_reg_to_var_int(iptr->dst, d);
727 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
729 var_to_reg_int(s1, src, REG_ITMP1);
730 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
732 store_reg_to_var_int(iptr->dst, d);
735 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
737 var_to_reg_int(s1, src, REG_ITMP1);
738 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
739 M_LSLL_IMM(s1, 48, d);
740 M_LSRA_IMM( d, 48, d);
741 store_reg_to_var_int(iptr->dst, d);
745 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
747 var_to_reg_int(s1, src->prev, REG_ITMP1);
748 var_to_reg_int(s2, src, REG_ITMP2);
749 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
751 store_reg_to_var_int(iptr->dst, d);
754 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
755 /* val.i = constant */
757 var_to_reg_int(s1, src, REG_ITMP1);
758 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
759 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
760 M_IADD_IMM(s1, iptr->val.i, d);
762 ICONST(REG_ITMP2, iptr->val.i);
763 M_IADD(s1, REG_ITMP2, d);
765 store_reg_to_var_int(iptr->dst, d);
768 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
770 var_to_reg_int(s1, src->prev, REG_ITMP1);
771 var_to_reg_int(s2, src, REG_ITMP2);
772 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
774 store_reg_to_var_int(iptr->dst, d);
777 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
778 /* val.l = constant */
780 var_to_reg_int(s1, src, REG_ITMP1);
781 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
782 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
783 M_LADD_IMM(s1, iptr->val.l, d);
785 LCONST(REG_ITMP2, iptr->val.l);
786 M_LADD(s1, REG_ITMP2, d);
788 store_reg_to_var_int(iptr->dst, d);
791 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
793 var_to_reg_int(s1, src->prev, REG_ITMP1);
794 var_to_reg_int(s2, src, REG_ITMP2);
795 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
797 store_reg_to_var_int(iptr->dst, d);
800 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
801 /* val.i = constant */
803 var_to_reg_int(s1, src, REG_ITMP1);
804 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
805 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
806 M_IADD_IMM(s1, -iptr->val.i, d);
808 ICONST(REG_ITMP2, iptr->val.i);
809 M_ISUB(s1, REG_ITMP2, d);
811 store_reg_to_var_int(iptr->dst, d);
814 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
816 var_to_reg_int(s1, src->prev, REG_ITMP1);
817 var_to_reg_int(s2, src, REG_ITMP2);
818 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
820 store_reg_to_var_int(iptr->dst, d);
823 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
824 /* val.l = constant */
826 var_to_reg_int(s1, src, REG_ITMP1);
827 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
828 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
829 M_LADD_IMM(s1, -iptr->val.l, d);
831 LCONST(REG_ITMP2, iptr->val.l);
832 M_LSUB(s1, REG_ITMP2, d);
834 store_reg_to_var_int(iptr->dst, d);
837 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
839 var_to_reg_int(s1, src->prev, REG_ITMP1);
840 var_to_reg_int(s2, src, REG_ITMP2);
841 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
846 store_reg_to_var_int(iptr->dst, d);
849 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
850 /* val.i = constant */
852 var_to_reg_int(s1, src, REG_ITMP1);
853 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
854 ICONST(REG_ITMP2, iptr->val.i);
855 M_IMUL(s1, REG_ITMP2);
859 store_reg_to_var_int(iptr->dst, d);
862 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
864 var_to_reg_int(s1, src->prev, REG_ITMP1);
865 var_to_reg_int(s2, src, REG_ITMP2);
866 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
871 store_reg_to_var_int(iptr->dst, d);
874 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
875 /* val.l = constant */
877 var_to_reg_int(s1, src, REG_ITMP1);
878 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
879 LCONST(REG_ITMP2, iptr->val.l);
880 M_LMUL(s1, REG_ITMP2);
884 store_reg_to_var_int(iptr->dst, d);
887 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
889 var_to_reg_int(s1, src->prev, REG_ITMP1);
890 var_to_reg_int(s2, src, REG_ITMP2);
891 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
897 store_reg_to_var_int(iptr->dst, d);
900 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
902 var_to_reg_int(s1, src->prev, REG_ITMP1);
903 var_to_reg_int(s2, src, REG_ITMP2);
904 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
910 store_reg_to_var_int(iptr->dst, d);
913 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
915 var_to_reg_int(s1, src->prev, REG_ITMP1);
916 var_to_reg_int(s2, src, REG_ITMP2);
917 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
923 store_reg_to_var_int(iptr->dst, d);
926 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
928 var_to_reg_int(s1, src->prev, REG_ITMP1);
929 var_to_reg_int(s2, src, REG_ITMP2);
930 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
936 store_reg_to_var_int(iptr->dst, d);
939 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
940 case ICMD_LDIVPOW2: /* val.i = constant */
942 var_to_reg_int(s1, src, REG_ITMP1);
943 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
944 M_LSRA_IMM(s1, 63, REG_ITMP2);
945 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
946 M_LADD(s1, REG_ITMP2, REG_ITMP2);
947 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
948 store_reg_to_var_int(iptr->dst, d);
951 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
953 var_to_reg_int(s1, src->prev, REG_ITMP1);
954 var_to_reg_int(s2, src, REG_ITMP2);
955 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
957 store_reg_to_var_int(iptr->dst, d);
960 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
961 /* val.i = constant */
963 var_to_reg_int(s1, src, REG_ITMP1);
964 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
965 M_ISLL_IMM(s1, iptr->val.i, d);
966 store_reg_to_var_int(iptr->dst, d);
969 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
971 var_to_reg_int(s1, src->prev, REG_ITMP1);
972 var_to_reg_int(s2, src, REG_ITMP2);
973 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
975 store_reg_to_var_int(iptr->dst, d);
978 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
979 /* val.i = constant */
981 var_to_reg_int(s1, src, REG_ITMP1);
982 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
983 M_ISRA_IMM(s1, iptr->val.i, d);
984 store_reg_to_var_int(iptr->dst, d);
987 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
989 var_to_reg_int(s1, src->prev, REG_ITMP1);
990 var_to_reg_int(s2, src, REG_ITMP2);
991 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
993 store_reg_to_var_int(iptr->dst, d);
996 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
997 /* val.i = constant */
999 var_to_reg_int(s1, src, REG_ITMP1);
1000 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1001 M_ISRL_IMM(s1, iptr->val.i, d);
1002 store_reg_to_var_int(iptr->dst, d);
1005 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1007 var_to_reg_int(s1, src->prev, REG_ITMP1);
1008 var_to_reg_int(s2, src, REG_ITMP2);
1009 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1011 store_reg_to_var_int(iptr->dst, d);
1014 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1015 /* val.i = constant */
1017 var_to_reg_int(s1, src, REG_ITMP1);
1018 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1019 M_LSLL_IMM(s1, iptr->val.i, d);
1020 store_reg_to_var_int(iptr->dst, d);
1023 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1025 var_to_reg_int(s1, src->prev, REG_ITMP1);
1026 var_to_reg_int(s2, src, REG_ITMP2);
1027 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1029 store_reg_to_var_int(iptr->dst, d);
1032 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1033 /* val.i = constant */
1035 var_to_reg_int(s1, src, REG_ITMP1);
1036 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1037 M_LSRA_IMM(s1, iptr->val.i, d);
1038 store_reg_to_var_int(iptr->dst, d);
1041 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1043 var_to_reg_int(s1, src->prev, REG_ITMP1);
1044 var_to_reg_int(s2, src, REG_ITMP2);
1045 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1047 store_reg_to_var_int(iptr->dst, d);
1050 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1051 /* val.i = constant */
1053 var_to_reg_int(s1, src, REG_ITMP1);
1054 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1055 M_LSRL_IMM(s1, iptr->val.i, d);
1056 store_reg_to_var_int(iptr->dst, d);
1059 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1062 var_to_reg_int(s1, src->prev, REG_ITMP1);
1063 var_to_reg_int(s2, src, REG_ITMP2);
1064 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1066 store_reg_to_var_int(iptr->dst, d);
1069 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1070 /* val.i = constant */
1072 var_to_reg_int(s1, src, REG_ITMP1);
1073 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1074 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1075 M_AND_IMM(s1, iptr->val.i, d);
1077 ICONST(REG_ITMP2, iptr->val.i);
1078 M_AND(s1, REG_ITMP2, d);
1080 store_reg_to_var_int(iptr->dst, d);
1083 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1084 /* val.i = constant */
1086 var_to_reg_int(s1, src, REG_ITMP1);
1087 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1089 M_MOV(s1, REG_ITMP1);
1092 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1093 M_AND_IMM(s1, iptr->val.i, d);
1096 M_ISUB(REG_ZERO, s1, d);
1097 M_AND_IMM(d, iptr->val.i, d);
1099 ICONST(REG_ITMP2, iptr->val.i);
1100 M_AND(s1, REG_ITMP2, d);
1103 M_ISUB(REG_ZERO, s1, d);
1104 M_AND(d, REG_ITMP2, d);
1106 M_ISUB(REG_ZERO, d, d);
1107 store_reg_to_var_int(iptr->dst, d);
1110 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1111 /* val.l = constant */
1113 var_to_reg_int(s1, src, REG_ITMP1);
1114 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1115 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1116 M_AND_IMM(s1, iptr->val.l, d);
1118 LCONST(REG_ITMP2, iptr->val.l);
1119 M_AND(s1, REG_ITMP2, d);
1121 store_reg_to_var_int(iptr->dst, d);
1124 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1125 /* val.l = constant */
1127 var_to_reg_int(s1, src, REG_ITMP1);
1128 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1130 M_MOV(s1, REG_ITMP1);
1133 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1134 M_AND_IMM(s1, iptr->val.l, d);
1137 M_LSUB(REG_ZERO, s1, d);
1138 M_AND_IMM(d, iptr->val.l, d);
1140 LCONST(REG_ITMP2, iptr->val.l);
1141 M_AND(s1, REG_ITMP2, d);
1144 M_LSUB(REG_ZERO, s1, d);
1145 M_AND(d, REG_ITMP2, d);
1147 M_LSUB(REG_ZERO, d, d);
1148 store_reg_to_var_int(iptr->dst, d);
1151 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1154 var_to_reg_int(s1, src->prev, REG_ITMP1);
1155 var_to_reg_int(s2, src, REG_ITMP2);
1156 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1158 store_reg_to_var_int(iptr->dst, d);
1161 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1162 /* val.i = constant */
1164 var_to_reg_int(s1, src, REG_ITMP1);
1165 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1166 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1167 M_OR_IMM(s1, iptr->val.i, d);
1169 ICONST(REG_ITMP2, iptr->val.i);
1170 M_OR(s1, REG_ITMP2, d);
1172 store_reg_to_var_int(iptr->dst, d);
1175 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1176 /* val.l = constant */
1178 var_to_reg_int(s1, src, REG_ITMP1);
1179 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1180 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1181 M_OR_IMM(s1, iptr->val.l, d);
1183 LCONST(REG_ITMP2, iptr->val.l);
1184 M_OR(s1, REG_ITMP2, d);
1186 store_reg_to_var_int(iptr->dst, d);
1189 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1192 var_to_reg_int(s1, src->prev, REG_ITMP1);
1193 var_to_reg_int(s2, src, REG_ITMP2);
1194 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1196 store_reg_to_var_int(iptr->dst, d);
1199 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1200 /* val.i = constant */
1202 var_to_reg_int(s1, src, REG_ITMP1);
1203 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1204 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1205 M_XOR_IMM(s1, iptr->val.i, d);
1207 ICONST(REG_ITMP2, iptr->val.i);
1208 M_XOR(s1, REG_ITMP2, d);
1210 store_reg_to_var_int(iptr->dst, d);
1213 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1214 /* val.l = constant */
1216 var_to_reg_int(s1, src, REG_ITMP1);
1217 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1218 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1219 M_XOR_IMM(s1, iptr->val.l, d);
1221 LCONST(REG_ITMP2, iptr->val.l);
1222 M_XOR(s1, REG_ITMP2, d);
1224 store_reg_to_var_int(iptr->dst, d);
1228 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1230 var_to_reg_int(s1, src->prev, REG_ITMP1);
1231 var_to_reg_int(s2, src, REG_ITMP2);
1232 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1233 M_CMPLT(s1, s2, REG_ITMP3);
1234 M_CMPLT(s2, s1, REG_ITMP1);
1235 M_LSUB(REG_ITMP1, REG_ITMP3, d);
1236 store_reg_to_var_int(iptr->dst, d);
1240 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1241 /* op1 = variable, val.i = constant */
1243 var = &(rd->locals[iptr->op1][TYPE_INT]);
1244 if (var->flags & INMEMORY) {
1246 M_LLD(s1, REG_SP, var->regoff * 8);
1249 M_IADD_IMM(s1, iptr->val.i, s1);
1250 if (var->flags & INMEMORY)
1251 M_LST(s1, REG_SP, var->regoff * 8);
1255 /* floating operations ************************************************/
1257 case ICMD_FNEG: /* ..., value ==> ..., - value */
1259 var_to_reg_flt(s1, src, REG_FTMP1);
1260 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1262 store_reg_to_var_flt(iptr->dst, d);
1265 case ICMD_DNEG: /* ..., value ==> ..., - value */
1267 var_to_reg_flt(s1, src, REG_FTMP1);
1268 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1270 store_reg_to_var_flt(iptr->dst, d);
1273 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1275 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1276 var_to_reg_flt(s2, src, REG_FTMP2);
1277 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1279 store_reg_to_var_flt(iptr->dst, d);
1282 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1284 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1285 var_to_reg_flt(s2, src, REG_FTMP2);
1286 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1288 store_reg_to_var_flt(iptr->dst, d);
1291 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1293 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1294 var_to_reg_flt(s2, src, REG_FTMP2);
1295 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1297 store_reg_to_var_flt(iptr->dst, d);
1300 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1302 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1303 var_to_reg_flt(s2, src, REG_FTMP2);
1304 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1306 store_reg_to_var_flt(iptr->dst, d);
1309 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1311 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1312 var_to_reg_flt(s2, src, REG_FTMP2);
1313 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1315 store_reg_to_var_flt(iptr->dst, d);
1318 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1320 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1321 var_to_reg_flt(s2, src, REG_FTMP2);
1322 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1324 store_reg_to_var_flt(iptr->dst, d);
1327 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1329 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1330 var_to_reg_flt(s2, src, REG_FTMP2);
1331 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1333 store_reg_to_var_flt(iptr->dst, d);
1336 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1338 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1339 var_to_reg_flt(s2, src, REG_FTMP2);
1340 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1342 store_reg_to_var_flt(iptr->dst, d);
1346 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1348 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1349 var_to_reg_flt(s2, src, REG_FTMP2);
1350 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1351 M_FDIV(s1,s2, REG_FTMP3);
1352 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1353 M_CVTLF(REG_FTMP3, REG_FTMP3);
1354 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1355 M_FSUB(s1, REG_FTMP3, d);
1356 store_reg_to_var_flt(iptr->dst, d);
1359 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1361 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1362 var_to_reg_flt(s2, src, REG_FTMP2);
1363 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1364 M_DDIV(s1,s2, REG_FTMP3);
1365 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1366 M_CVTLD(REG_FTMP3, REG_FTMP3);
1367 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1368 M_DSUB(s1, REG_FTMP3, d);
1369 store_reg_to_var_flt(iptr->dst, d);
1373 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1375 var_to_reg_int(s1, src, REG_ITMP1);
1376 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1379 store_reg_to_var_flt(iptr->dst, d);
1382 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1384 var_to_reg_int(s1, src, REG_ITMP1);
1385 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1388 store_reg_to_var_flt(iptr->dst, d);
1391 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1393 var_to_reg_flt(s1, src, REG_FTMP1);
1394 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1395 M_TRUNCFI(s1, REG_FTMP1);
1396 M_MOVDI(REG_FTMP1, d);
1398 store_reg_to_var_int(iptr->dst, d);
1401 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1403 var_to_reg_flt(s1, src, REG_FTMP1);
1404 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1405 M_TRUNCDI(s1, REG_FTMP1);
1406 M_MOVDI(REG_FTMP1, d);
1408 store_reg_to_var_int(iptr->dst, d);
1411 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1413 var_to_reg_flt(s1, src, REG_FTMP1);
1414 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1415 M_TRUNCFL(s1, REG_FTMP1);
1416 M_MOVDL(REG_FTMP1, d);
1418 store_reg_to_var_int(iptr->dst, d);
1421 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1423 var_to_reg_flt(s1, src, REG_FTMP1);
1424 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1425 M_TRUNCDL(s1, REG_FTMP1);
1426 M_MOVDL(REG_FTMP1, d);
1428 store_reg_to_var_int(iptr->dst, d);
1431 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1433 var_to_reg_flt(s1, src, REG_FTMP1);
1434 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1436 store_reg_to_var_flt(iptr->dst, d);
1439 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1441 var_to_reg_flt(s1, src, REG_FTMP1);
1442 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1444 store_reg_to_var_flt(iptr->dst, d);
1447 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1449 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1450 var_to_reg_flt(s2, src, REG_FTMP2);
1451 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1454 M_LADD_IMM(REG_ZERO, 1, d);
1458 M_LSUB_IMM(REG_ZERO, 1, d);
1459 M_CMOVT(REG_ZERO, d);
1460 store_reg_to_var_int(iptr->dst, d);
1463 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1465 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1466 var_to_reg_flt(s2, src, REG_FTMP2);
1467 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1470 M_LADD_IMM(REG_ZERO, 1, d);
1474 M_LSUB_IMM(REG_ZERO, 1, d);
1475 M_CMOVT(REG_ZERO, d);
1476 store_reg_to_var_int(iptr->dst, d);
1479 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1481 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1482 var_to_reg_flt(s2, src, REG_FTMP2);
1483 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1486 M_LSUB_IMM(REG_ZERO, 1, d);
1490 M_LADD_IMM(REG_ZERO, 1, d);
1491 M_CMOVT(REG_ZERO, d);
1492 store_reg_to_var_int(iptr->dst, d);
1495 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1497 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1498 var_to_reg_flt(s2, src, REG_FTMP2);
1499 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1502 M_LSUB_IMM(REG_ZERO, 1, d);
1506 M_LADD_IMM(REG_ZERO, 1, d);
1507 M_CMOVT(REG_ZERO, d);
1508 store_reg_to_var_int(iptr->dst, d);
1512 /* memory operations **************************************************/
1514 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1516 var_to_reg_int(s1, src, REG_ITMP1);
1517 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1518 gen_nullptr_check(s1);
1519 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1520 store_reg_to_var_int(iptr->dst, d);
1523 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1525 var_to_reg_int(s1, src->prev, REG_ITMP1);
1526 var_to_reg_int(s2, src, REG_ITMP2);
1527 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1528 if (iptr->op1 == 0) {
1529 gen_nullptr_check(s1);
1532 M_AADD(s2, s1, REG_ITMP3);
1533 M_BLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1534 store_reg_to_var_int(iptr->dst, d);
1537 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1539 var_to_reg_int(s1, src->prev, REG_ITMP1);
1540 var_to_reg_int(s2, src, REG_ITMP2);
1541 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1542 if (iptr->op1 == 0) {
1543 gen_nullptr_check(s1);
1546 M_AADD(s2, s1, REG_ITMP3);
1547 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1548 M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1549 store_reg_to_var_int(iptr->dst, d);
1552 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1554 var_to_reg_int(s1, src->prev, REG_ITMP1);
1555 var_to_reg_int(s2, src, REG_ITMP2);
1556 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1557 if (iptr->op1 == 0) {
1558 gen_nullptr_check(s1);
1561 M_AADD(s2, s1, REG_ITMP3);
1562 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1563 M_SLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1564 store_reg_to_var_int(iptr->dst, d);
1567 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1569 var_to_reg_int(s1, src->prev, REG_ITMP1);
1570 var_to_reg_int(s2, src, REG_ITMP2);
1571 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1572 if (iptr->op1 == 0) {
1573 gen_nullptr_check(s1);
1576 M_ASLL_IMM(s2, 2, REG_ITMP3);
1577 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1578 M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
1579 store_reg_to_var_int(iptr->dst, d);
1582 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1584 var_to_reg_int(s1, src->prev, REG_ITMP1);
1585 var_to_reg_int(s2, src, REG_ITMP2);
1586 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1587 if (iptr->op1 == 0) {
1588 gen_nullptr_check(s1);
1591 M_ASLL_IMM(s2, 3, REG_ITMP3);
1592 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1593 M_LLD(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
1594 store_reg_to_var_int(iptr->dst, d);
1597 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1599 var_to_reg_int(s1, src->prev, REG_ITMP1);
1600 var_to_reg_int(s2, src, REG_ITMP2);
1601 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1602 if (iptr->op1 == 0) {
1603 gen_nullptr_check(s1);
1606 M_ASLL_IMM(s2, 2, REG_ITMP3);
1607 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1608 M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
1609 store_reg_to_var_flt(iptr->dst, d);
1612 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1614 var_to_reg_int(s1, src->prev, REG_ITMP1);
1615 var_to_reg_int(s2, src, REG_ITMP2);
1616 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1617 if (iptr->op1 == 0) {
1618 gen_nullptr_check(s1);
1621 M_ASLL_IMM(s2, 3, REG_ITMP3);
1622 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1623 M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
1624 store_reg_to_var_flt(iptr->dst, d);
1627 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1629 var_to_reg_int(s1, src->prev, REG_ITMP1);
1630 var_to_reg_int(s2, src, REG_ITMP2);
1631 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1632 if (iptr->op1 == 0) {
1633 gen_nullptr_check(s1);
1636 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1637 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1638 M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
1639 store_reg_to_var_int(iptr->dst, d);
1643 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1645 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1646 var_to_reg_int(s2, src->prev, REG_ITMP2);
1647 if (iptr->op1 == 0) {
1648 gen_nullptr_check(s1);
1651 var_to_reg_int(s3, src, REG_ITMP3);
1652 M_AADD(s2, s1, REG_ITMP1);
1653 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1656 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1657 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1659 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1660 var_to_reg_int(s2, src->prev, REG_ITMP2);
1661 if (iptr->op1 == 0) {
1662 gen_nullptr_check(s1);
1665 var_to_reg_int(s3, src, REG_ITMP3);
1666 M_AADD(s2, s1, REG_ITMP1);
1667 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1668 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1671 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1673 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1674 var_to_reg_int(s2, src->prev, REG_ITMP2);
1675 if (iptr->op1 == 0) {
1676 gen_nullptr_check(s1);
1679 var_to_reg_int(s3, src, REG_ITMP3);
1680 M_ASLL_IMM(s2, 2, REG_ITMP2);
1681 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1682 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1685 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1687 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1688 var_to_reg_int(s2, src->prev, REG_ITMP2);
1689 if (iptr->op1 == 0) {
1690 gen_nullptr_check(s1);
1693 var_to_reg_int(s3, src, REG_ITMP3);
1694 M_ASLL_IMM(s2, 3, REG_ITMP2);
1695 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1696 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1699 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1701 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1702 var_to_reg_int(s2, src->prev, REG_ITMP2);
1703 if (iptr->op1 == 0) {
1704 gen_nullptr_check(s1);
1707 var_to_reg_flt(s3, src, REG_FTMP1);
1708 M_ASLL_IMM(s2, 2, REG_ITMP2);
1709 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1710 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1713 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1715 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1716 var_to_reg_int(s2, src->prev, REG_ITMP2);
1717 if (iptr->op1 == 0) {
1718 gen_nullptr_check(s1);
1721 var_to_reg_flt(s3, src, REG_FTMP1);
1722 M_ASLL_IMM(s2, 3, REG_ITMP2);
1723 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1724 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1728 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1730 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1731 var_to_reg_int(s2, src->prev, REG_ITMP2);
1732 if (iptr->op1 == 0) {
1733 gen_nullptr_check(s1);
1736 var_to_reg_int(s3, src, REG_ITMP3);
1738 M_MOV(s1, rd->argintregs[0]);
1739 M_MOV(s3, rd->argintregs[1]);
1740 disp = dseg_addaddress(cd, BUILTIN_canstore);
1741 M_ALD(REG_ITMP3, REG_PV, disp);
1742 M_JSR(REG_RA, REG_ITMP3);
1745 M_BEQZ(REG_RESULT, 0);
1746 codegen_addxstorerefs(cd, mcodeptr);
1749 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1750 var_to_reg_int(s2, src->prev, REG_ITMP2);
1751 var_to_reg_int(s3, src, REG_ITMP3);
1752 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1753 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1754 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1758 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1760 var_to_reg_int(s1, src->prev, REG_ITMP1);
1761 var_to_reg_int(s2, src, REG_ITMP2);
1762 if (iptr->op1 == 0) {
1763 gen_nullptr_check(s1);
1766 M_ASLL_IMM(s2, 2, REG_ITMP2);
1767 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1768 M_IST(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1771 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1773 var_to_reg_int(s1, src->prev, REG_ITMP1);
1774 var_to_reg_int(s2, src, REG_ITMP2);
1775 if (iptr->op1 == 0) {
1776 gen_nullptr_check(s1);
1779 M_ASLL_IMM(s2, 3, REG_ITMP2);
1780 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1781 M_LST(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1784 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1786 var_to_reg_int(s1, src->prev, REG_ITMP1);
1787 var_to_reg_int(s2, src, REG_ITMP2);
1788 if (iptr->op1 == 0) {
1789 gen_nullptr_check(s1);
1792 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1793 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1794 M_AST(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1797 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1799 var_to_reg_int(s1, src->prev, REG_ITMP1);
1800 var_to_reg_int(s2, src, REG_ITMP2);
1801 if (iptr->op1 == 0) {
1802 gen_nullptr_check(s1);
1805 M_AADD(s2, s1, REG_ITMP1);
1806 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1809 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1810 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1812 var_to_reg_int(s1, src->prev, REG_ITMP1);
1813 var_to_reg_int(s2, src, REG_ITMP2);
1814 if (iptr->op1 == 0) {
1815 gen_nullptr_check(s1);
1818 M_AADD(s2, s1, REG_ITMP1);
1819 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1820 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
1824 case ICMD_GETSTATIC: /* ... ==> ..., value */
1825 /* op1 = type, val.a = field address */
1828 disp = dseg_addaddress(cd, NULL);
1830 codegen_addpatchref(cd, mcodeptr,
1831 PATCHER_get_putstatic,
1832 (unresolved_field *) iptr->target, disp);
1834 if (opt_showdisassemble) {
1839 fieldinfo *fi = iptr->val.a;
1841 disp = dseg_addaddress(cd, &(fi->value));
1843 if (!fi->class->initialized) {
1844 codegen_addpatchref(cd, mcodeptr,
1845 PATCHER_clinit, fi->class, 0);
1847 if (opt_showdisassemble) {
1853 M_ALD(REG_ITMP1, REG_PV, disp);
1854 switch (iptr->op1) {
1856 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1857 M_ILD_INTERN(d, REG_ITMP1, 0);
1858 store_reg_to_var_int(iptr->dst, d);
1861 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1862 M_LLD_INTERN(d, REG_ITMP1, 0);
1863 store_reg_to_var_int(iptr->dst, d);
1866 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1867 M_ALD_INTERN(d, REG_ITMP1, 0);
1868 store_reg_to_var_int(iptr->dst, d);
1871 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1872 M_FLD_INTERN(d, REG_ITMP1, 0);
1873 store_reg_to_var_flt(iptr->dst, d);
1876 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1877 M_DLD_INTERN(d, REG_ITMP1, 0);
1878 store_reg_to_var_flt(iptr->dst, d);
1883 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1884 /* op1 = type, val.a = field address */
1887 disp = dseg_addaddress(cd, NULL);
1889 codegen_addpatchref(cd, mcodeptr,
1890 PATCHER_get_putstatic,
1891 (unresolved_field *) iptr->target, disp);
1893 if (opt_showdisassemble) {
1898 fieldinfo *fi = iptr->val.a;
1900 disp = dseg_addaddress(cd, &(fi->value));
1902 if (!fi->class->initialized) {
1903 codegen_addpatchref(cd, mcodeptr,
1904 PATCHER_clinit, fi->class, 0);
1906 if (opt_showdisassemble) {
1912 M_ALD(REG_ITMP1, REG_PV, disp);
1913 switch (iptr->op1) {
1915 var_to_reg_int(s2, src, REG_ITMP2);
1916 M_IST_INTERN(s2, REG_ITMP1, 0);
1919 var_to_reg_int(s2, src, REG_ITMP2);
1920 M_LST_INTERN(s2, REG_ITMP1, 0);
1923 var_to_reg_int(s2, src, REG_ITMP2);
1924 M_AST_INTERN(s2, REG_ITMP1, 0);
1927 var_to_reg_flt(s2, src, REG_FTMP2);
1928 M_FST_INTERN(s2, REG_ITMP1, 0);
1931 var_to_reg_flt(s2, src, REG_FTMP2);
1932 M_DST_INTERN(s2, REG_ITMP1, 0);
1937 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1938 /* val = value (in current instruction) */
1939 /* op1 = type, val.a = field address (in */
1940 /* following NOP) */
1942 if (!iptr[1].val.a) {
1943 disp = dseg_addaddress(cd, NULL);
1945 codegen_addpatchref(cd, mcodeptr,
1946 PATCHER_get_putstatic,
1947 (unresolved_field *) iptr[1].target, disp);
1949 if (opt_showdisassemble) {
1954 fieldinfo *fi = iptr[1].val.a;
1956 disp = dseg_addaddress(cd, &(fi->value));
1958 if (!fi->class->initialized) {
1959 codegen_addpatchref(cd, mcodeptr,
1960 PATCHER_clinit, fi->class, 0);
1962 if (opt_showdisassemble) {
1968 M_ALD(REG_ITMP1, REG_PV, disp);
1969 switch (iptr->op1) {
1971 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1974 M_LST_INTERN(REG_ZERO, REG_ITMP1, 0);
1977 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1980 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1983 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1989 case ICMD_GETFIELD: /* ... ==> ..., value */
1990 /* op1 = type, val.i = field offset */
1992 var_to_reg_int(s1, src, REG_ITMP1);
1993 gen_nullptr_check(s1);
1996 codegen_addpatchref(cd, mcodeptr,
1997 PATCHER_get_putfield,
1998 (unresolved_field *) iptr->target, 0);
2000 if (opt_showdisassemble) {
2007 a = ((fieldinfo *) (iptr->val.a))->offset;
2010 switch (iptr->op1) {
2012 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2014 store_reg_to_var_int(iptr->dst, d);
2017 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2019 store_reg_to_var_int(iptr->dst, d);
2022 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2024 store_reg_to_var_int(iptr->dst, d);
2027 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2029 store_reg_to_var_flt(iptr->dst, d);
2032 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2034 store_reg_to_var_flt(iptr->dst, d);
2039 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2040 /* op1 = type, val.a = field address */
2042 var_to_reg_int(s1, src->prev, REG_ITMP1);
2043 gen_nullptr_check(s1);
2045 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2046 var_to_reg_int(s2, src, REG_ITMP2);
2048 var_to_reg_flt(s2, src, REG_FTMP2);
2052 codegen_addpatchref(cd, mcodeptr,
2053 PATCHER_get_putfield,
2054 (unresolved_field *) iptr->target, 0);
2056 if (opt_showdisassemble) {
2063 a = ((fieldinfo *) (iptr->val.a))->offset;
2066 switch (iptr->op1) {
2085 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2086 /* val = value (in current instruction) */
2087 /* op1 = type, val.a = field address (in */
2088 /* following NOP) */
2090 var_to_reg_int(s1, src, REG_ITMP1);
2091 gen_nullptr_check(s1);
2093 if (!iptr[1].val.a) {
2094 codegen_addpatchref(cd, mcodeptr,
2095 PATCHER_get_putfield,
2096 (unresolved_field *) iptr[1].target, 0);
2098 if (opt_showdisassemble) {
2105 a = ((fieldinfo *) (iptr[1].val.a))->offset;
2108 switch (iptr[1].op1) {
2110 M_IST(REG_ZERO, s1, a);
2113 M_LST(REG_ZERO, s1, a);
2116 M_AST(REG_ZERO, s1, a);
2119 M_FST(REG_ZERO, s1, a);
2122 M_DST(REG_ZERO, s1, a);
2128 /* branch operations **************************************************/
2130 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2132 var_to_reg_int(s1, src, REG_ITMP1);
2133 M_INTMOVE(s1, REG_ITMP1_XPTR);
2136 codegen_addpatchref(cd, mcodeptr,
2137 PATCHER_athrow_areturn,
2138 (unresolved_class *) iptr->val.a, 0);
2140 if (opt_showdisassemble) {
2145 disp = dseg_addaddress(cd, asm_handle_exception);
2146 M_ALD(REG_ITMP2, REG_PV, disp);
2147 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2149 M_NOP; /* nop ensures that XPC is less than the end */
2150 /* of basic block */
2154 case ICMD_GOTO: /* ... ==> ... */
2155 /* op1 = target JavaVM pc */
2157 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2162 case ICMD_JSR: /* ... ==> ... */
2163 /* op1 = target JavaVM pc */
2165 dseg_addtarget(cd, (basicblock *) iptr->target);
2166 M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
2167 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2171 case ICMD_RET: /* ... ==> ... */
2172 /* op1 = local variable */
2173 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2174 if (var->flags & INMEMORY) {
2175 M_ALD(REG_ITMP1, REG_SP, var->regoff * 8);
2183 case ICMD_IFNULL: /* ..., value ==> ... */
2184 /* op1 = target JavaVM pc */
2186 var_to_reg_int(s1, src, REG_ITMP1);
2188 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2192 case ICMD_IFNONNULL: /* ..., value ==> ... */
2193 /* op1 = target JavaVM pc */
2195 var_to_reg_int(s1, src, REG_ITMP1);
2197 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2201 case ICMD_IFEQ: /* ..., value ==> ... */
2202 /* op1 = target JavaVM pc, val.i = constant */
2204 var_to_reg_int(s1, src, REG_ITMP1);
2205 if (iptr->val.i == 0) {
2208 ICONST(REG_ITMP2, iptr->val.i);
2209 M_BEQ(s1, REG_ITMP2, 0);
2211 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2215 case ICMD_IFLT: /* ..., value ==> ... */
2216 /* op1 = target JavaVM pc, val.i = constant */
2218 var_to_reg_int(s1, src, REG_ITMP1);
2219 if (iptr->val.i == 0) {
2222 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2223 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2225 ICONST(REG_ITMP2, iptr->val.i);
2226 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2228 M_BNEZ(REG_ITMP1, 0);
2230 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2234 case ICMD_IFLE: /* ..., value ==> ... */
2235 /* op1 = target JavaVM pc, val.i = constant */
2237 var_to_reg_int(s1, src, REG_ITMP1);
2238 if (iptr->val.i == 0) {
2242 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2243 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2244 M_BNEZ(REG_ITMP1, 0);
2247 ICONST(REG_ITMP2, iptr->val.i);
2248 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2249 M_BEQZ(REG_ITMP1, 0);
2252 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2256 case ICMD_IFNE: /* ..., value ==> ... */
2257 /* op1 = target JavaVM pc, val.i = constant */
2259 var_to_reg_int(s1, src, REG_ITMP1);
2260 if (iptr->val.i == 0) {
2264 ICONST(REG_ITMP2, iptr->val.i);
2265 M_BNE(s1, REG_ITMP2, 0);
2267 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2271 case ICMD_IFGT: /* ..., value ==> ... */
2272 /* op1 = target JavaVM pc, val.i = constant */
2274 var_to_reg_int(s1, src, REG_ITMP1);
2275 if (iptr->val.i == 0) {
2279 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2280 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2281 M_BEQZ(REG_ITMP1, 0);
2284 ICONST(REG_ITMP2, iptr->val.i);
2285 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2286 M_BNEZ(REG_ITMP1, 0);
2289 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2293 case ICMD_IFGE: /* ..., value ==> ... */
2294 /* op1 = target JavaVM pc, val.i = constant */
2296 var_to_reg_int(s1, src, REG_ITMP1);
2297 if (iptr->val.i == 0) {
2301 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2302 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2305 ICONST(REG_ITMP2, iptr->val.i);
2306 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2308 M_BEQZ(REG_ITMP1, 0);
2310 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2314 case ICMD_IF_LEQ: /* ..., value ==> ... */
2315 /* op1 = target JavaVM pc, val.l = constant */
2317 var_to_reg_int(s1, src, REG_ITMP1);
2318 if (iptr->val.l == 0) {
2322 LCONST(REG_ITMP2, iptr->val.l);
2323 M_BEQ(s1, REG_ITMP2, 0);
2325 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2329 case ICMD_IF_LLT: /* ..., value ==> ... */
2330 /* op1 = target JavaVM pc, val.l = constant */
2332 var_to_reg_int(s1, src, REG_ITMP1);
2333 if (iptr->val.l == 0) {
2337 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2338 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2341 LCONST(REG_ITMP2, iptr->val.l);
2342 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2344 M_BNEZ(REG_ITMP1, 0);
2346 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2350 case ICMD_IF_LLE: /* ..., value ==> ... */
2351 /* op1 = target JavaVM pc, val.l = constant */
2353 var_to_reg_int(s1, src, REG_ITMP1);
2354 if (iptr->val.l == 0) {
2358 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2359 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2360 M_BNEZ(REG_ITMP1, 0);
2363 LCONST(REG_ITMP2, iptr->val.l);
2364 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2365 M_BEQZ(REG_ITMP1, 0);
2368 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2372 case ICMD_IF_LNE: /* ..., value ==> ... */
2373 /* op1 = target JavaVM pc, val.l = constant */
2375 var_to_reg_int(s1, src, REG_ITMP1);
2376 if (iptr->val.l == 0) {
2380 LCONST(REG_ITMP2, iptr->val.l);
2381 M_BNE(s1, REG_ITMP2, 0);
2383 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2387 case ICMD_IF_LGT: /* ..., value ==> ... */
2388 /* op1 = target JavaVM pc, val.l = constant */
2390 var_to_reg_int(s1, src, REG_ITMP1);
2391 if (iptr->val.l == 0) {
2395 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2396 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2397 M_BEQZ(REG_ITMP1, 0);
2400 LCONST(REG_ITMP2, iptr->val.l);
2401 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2402 M_BNEZ(REG_ITMP1, 0);
2405 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2409 case ICMD_IF_LGE: /* ..., value ==> ... */
2410 /* op1 = target JavaVM pc, val.l = constant */
2412 var_to_reg_int(s1, src, REG_ITMP1);
2413 if (iptr->val.l == 0) {
2417 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2418 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2421 LCONST(REG_ITMP2, iptr->val.l);
2422 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2424 M_BEQZ(REG_ITMP1, 0);
2426 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2430 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2431 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2432 case ICMD_IF_ACMPEQ:
2434 var_to_reg_int(s1, src->prev, REG_ITMP1);
2435 var_to_reg_int(s2, src, REG_ITMP2);
2437 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2441 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2442 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2443 case ICMD_IF_ACMPNE:
2445 var_to_reg_int(s1, src->prev, REG_ITMP1);
2446 var_to_reg_int(s2, src, REG_ITMP2);
2448 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2452 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2453 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2455 var_to_reg_int(s1, src->prev, REG_ITMP1);
2456 var_to_reg_int(s2, src, REG_ITMP2);
2457 M_CMPLT(s1, s2, REG_ITMP1);
2458 M_BNEZ(REG_ITMP1, 0);
2459 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2463 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2464 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2466 var_to_reg_int(s1, src->prev, REG_ITMP1);
2467 var_to_reg_int(s2, src, REG_ITMP2);
2468 M_CMPGT(s1, s2, REG_ITMP1);
2469 M_BNEZ(REG_ITMP1, 0);
2470 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2474 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2475 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2477 var_to_reg_int(s1, src->prev, REG_ITMP1);
2478 var_to_reg_int(s2, src, REG_ITMP2);
2479 M_CMPGT(s1, s2, REG_ITMP1);
2480 M_BEQZ(REG_ITMP1, 0);
2481 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2485 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2486 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2488 var_to_reg_int(s1, src->prev, REG_ITMP1);
2489 var_to_reg_int(s2, src, REG_ITMP2);
2490 M_CMPLT(s1, s2, REG_ITMP1);
2491 M_BEQZ(REG_ITMP1, 0);
2492 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2496 #ifdef CONDITIONAL_LOADCONST
2497 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2499 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2502 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2503 /* val.i = constant */
2505 var_to_reg_int(s1, src, REG_ITMP1);
2506 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2508 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2509 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2510 M_CMPEQ(s1, REG_ZERO, d);
2511 store_reg_to_var_int(iptr->dst, d);
2514 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2515 M_CMPEQ(s1, REG_ZERO, d);
2517 store_reg_to_var_int(iptr->dst, d);
2521 M_MOV(s1, REG_ITMP1);
2524 ICONST(d, iptr[1].val.i);
2526 if ((s3 >= 0) && (s3 <= 255)) {
2527 M_CMOVEQ_IMM(s1, s3, d);
2529 ICONST(REG_ITMP3, s3);
2530 M_CMOVEQ(s1, REG_ITMP3, d);
2532 store_reg_to_var_int(iptr->dst, d);
2535 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2536 /* val.i = constant */
2538 var_to_reg_int(s1, src, REG_ITMP1);
2539 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2541 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2542 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2543 M_CMPEQ(s1, REG_ZERO, d);
2544 store_reg_to_var_int(iptr->dst, d);
2547 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2548 M_CMPEQ(s1, REG_ZERO, d);
2550 store_reg_to_var_int(iptr->dst, d);
2554 M_MOV(s1, REG_ITMP1);
2557 ICONST(d, iptr[1].val.i);
2559 if ((s3 >= 0) && (s3 <= 255)) {
2560 M_CMOVNE_IMM(s1, s3, d);
2562 ICONST(REG_ITMP3, s3);
2563 M_CMOVNE(s1, REG_ITMP3, d);
2565 store_reg_to_var_int(iptr->dst, d);
2568 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2569 /* val.i = constant */
2571 var_to_reg_int(s1, src, REG_ITMP1);
2572 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2574 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2575 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2576 M_CMPLT(s1, REG_ZERO, d);
2577 store_reg_to_var_int(iptr->dst, d);
2580 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2581 M_CMPLE(REG_ZERO, s1, d);
2582 store_reg_to_var_int(iptr->dst, d);
2586 M_MOV(s1, REG_ITMP1);
2589 ICONST(d, iptr[1].val.i);
2591 if ((s3 >= 0) && (s3 <= 255)) {
2592 M_CMOVLT_IMM(s1, s3, d);
2594 ICONST(REG_ITMP3, s3);
2595 M_CMOVLT(s1, REG_ITMP3, d);
2597 store_reg_to_var_int(iptr->dst, d);
2600 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2601 /* val.i = constant */
2603 var_to_reg_int(s1, src, REG_ITMP1);
2604 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2606 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2607 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2608 M_CMPLE(REG_ZERO, s1, d);
2609 store_reg_to_var_int(iptr->dst, d);
2612 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2613 M_CMPLT(s1, REG_ZERO, d);
2614 store_reg_to_var_int(iptr->dst, d);
2618 M_MOV(s1, REG_ITMP1);
2621 ICONST(d, iptr[1].val.i);
2623 if ((s3 >= 0) && (s3 <= 255)) {
2624 M_CMOVGE_IMM(s1, s3, d);
2626 ICONST(REG_ITMP3, s3);
2627 M_CMOVGE(s1, REG_ITMP3, d);
2629 store_reg_to_var_int(iptr->dst, d);
2632 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2633 /* val.i = constant */
2635 var_to_reg_int(s1, src, REG_ITMP1);
2636 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2638 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2639 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2640 M_CMPLT(REG_ZERO, s1, d);
2641 store_reg_to_var_int(iptr->dst, d);
2644 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2645 M_CMPLE(s1, REG_ZERO, d);
2646 store_reg_to_var_int(iptr->dst, d);
2650 M_MOV(s1, REG_ITMP1);
2653 ICONST(d, iptr[1].val.i);
2655 if ((s3 >= 0) && (s3 <= 255)) {
2656 M_CMOVGT_IMM(s1, s3, d);
2658 ICONST(REG_ITMP3, s3);
2659 M_CMOVGT(s1, REG_ITMP3, d);
2661 store_reg_to_var_int(iptr->dst, d);
2664 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2665 /* val.i = constant */
2667 var_to_reg_int(s1, src, REG_ITMP1);
2668 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2670 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2671 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2672 M_CMPLE(s1, REG_ZERO, d);
2673 store_reg_to_var_int(iptr->dst, d);
2676 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2677 M_CMPLT(REG_ZERO, s1, d);
2678 store_reg_to_var_int(iptr->dst, d);
2682 M_MOV(s1, REG_ITMP1);
2685 ICONST(d, iptr[1].val.i);
2687 if ((s3 >= 0) && (s3 <= 255)) {
2688 M_CMOVLE_IMM(s1, s3, d);
2690 ICONST(REG_ITMP3, s3);
2691 M_CMOVLE(s1, REG_ITMP3, d);
2693 store_reg_to_var_int(iptr->dst, d);
2698 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2701 var_to_reg_int(s1, src, REG_RESULT);
2702 M_INTMOVE(s1, REG_RESULT);
2703 goto nowperformreturn;
2705 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2707 var_to_reg_int(s1, src, REG_RESULT);
2708 M_INTMOVE(s1, REG_RESULT);
2711 codegen_addpatchref(cd, mcodeptr,
2712 PATCHER_athrow_areturn,
2713 (unresolved_class *) iptr->val.a, 0);
2715 if (opt_showdisassemble) {
2719 goto nowperformreturn;
2721 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2723 var_to_reg_flt(s1, src, REG_FRESULT);
2725 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2726 M_TFLTMOVE(t, s1, REG_FRESULT);
2728 goto nowperformreturn;
2730 case ICMD_RETURN: /* ... ==> ... */
2736 p = parentargs_base;
2738 /* call trace function */
2741 M_LDA(REG_SP, REG_SP, -3 * 8);
2742 M_LST(REG_RA, REG_SP, 0 * 8);
2743 M_LST(REG_RESULT, REG_SP, 1 * 8);
2744 M_DST(REG_FRESULT, REG_SP, 2 * 8);
2746 disp = dseg_addaddress(cd, m);
2747 M_ALD(rd->argintregs[0], REG_PV, disp);
2748 M_MOV(REG_RESULT, rd->argintregs[1]);
2749 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2750 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
2752 disp = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2753 M_ALD(REG_ITMP3, REG_PV, disp);
2754 M_JSR(REG_RA, REG_ITMP3);
2757 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
2758 M_LLD(REG_RESULT, REG_SP, 1 * 8);
2759 M_LLD(REG_RA, REG_SP, 0 * 8);
2760 M_LDA(REG_SP, REG_SP, 3 * 8);
2763 #if defined(USE_THREADS)
2764 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2765 disp = dseg_addaddress(cd, (void *) builtin_monitorexit);
2766 M_ALD(REG_ITMP3, REG_PV, disp);
2768 /* we need to save the proper return value */
2770 switch (iptr->opc) {
2774 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2775 M_JSR(REG_RA, REG_ITMP3);
2776 M_LST(REG_RESULT, REG_SP, rd->memuse * 8); /* delay slot */
2780 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2781 M_JSR(REG_RA, REG_ITMP3);
2782 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8); /* delay slot */
2785 M_JSR(REG_RA, REG_ITMP3);
2786 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8); /* delay*/
2790 /* and now restore the proper return value */
2792 switch (iptr->opc) {
2796 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
2800 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
2806 /* restore return address */
2808 if (!m->isleafmethod) {
2809 p--; M_ALD(REG_RA, REG_SP, p * 8);
2812 /* restore saved registers */
2814 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2815 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
2817 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2818 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2821 /* deallocate stack and return */
2823 if (parentargs_base) {
2826 disp = parentargs_base * 8;
2827 lo = (short) (disp);
2828 hi = (short) (((disp) - lo) >> 16);
2832 M_LADD_IMM(REG_SP, lo, REG_SP); /* delay slot */
2834 M_LUI(REG_ITMP3,hi);
2835 M_LADD_IMM(REG_ITMP3,lo,REG_ITMP3);
2837 M_LADD(REG_ITMP3,REG_SP,REG_SP); /* delay slot */
2850 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2855 tptr = (void **) iptr->target;
2857 s4ptr = iptr->val.a;
2858 l = s4ptr[1]; /* low */
2859 i = s4ptr[2]; /* high */
2861 var_to_reg_int(s1, src, REG_ITMP1);
2863 {M_INTMOVE(s1, REG_ITMP1);}
2864 else if (l <= 32768) {
2865 M_IADD_IMM(s1, -l, REG_ITMP1);
2868 ICONST(REG_ITMP2, l);
2869 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2875 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
2876 M_BEQZ(REG_ITMP2, 0);
2877 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2878 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
2880 /* build jump table top down and use address of lowest entry */
2882 /* s4ptr += 3 + i; */
2886 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2887 dseg_addtarget(cd, (basicblock *) tptr[0]);
2892 /* length of dataseg after last dseg_addtarget is used by load */
2894 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2895 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2902 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2904 s4 i, /*l, */val, *s4ptr;
2907 tptr = (void **) iptr->target;
2909 s4ptr = iptr->val.a;
2910 /*l = s4ptr[0];*/ /* default */
2911 i = s4ptr[1]; /* count */
2913 MCODECHECK((i<<2)+8);
2914 var_to_reg_int(s1, src, REG_ITMP1);
2920 ICONST(REG_ITMP2, val);
2921 M_BEQ(s1, REG_ITMP2, 0);
2922 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2927 tptr = (void **) iptr->target;
2928 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2935 case ICMD_BUILTIN: /* ..., arg1 ==> ... */
2936 /* op1 = arg count val.a = builtintable entry */
2942 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2943 /* op1 = arg count, val.a = method pointer */
2945 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2946 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2947 case ICMD_INVOKEINTERFACE:
2952 unresolved_method *um = iptr->target;
2953 md = um->methodref->parseddesc.md;
2955 md = lm->parseddesc;
2959 s3 = md->paramcount;
2961 MCODECHECK((s3 << 1) + 64);
2963 /* copy arguments to registers or stack location */
2965 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2966 if (src->varkind == ARGVAR)
2968 if (IS_INT_LNG_TYPE(src->type)) {
2969 if (!md->params[s3].inmemory) {
2970 s1 = rd->argintregs[md->params[s3].regoff];
2971 var_to_reg_int(d, src, s1);
2974 var_to_reg_int(d, src, REG_ITMP1);
2975 M_LST(d, REG_SP, md->params[s3].regoff * 8);
2979 if (!md->params[s3].inmemory) {
2980 s1 = rd->argfltregs[md->params[s3].regoff];
2981 var_to_reg_flt(d, src, s1);
2982 M_TFLTMOVE(src->type, d, s1);
2984 var_to_reg_flt(d, src, REG_FTMP1);
2985 M_DST(d, REG_SP, md->params[s3].regoff * 8);
2990 switch (iptr->opc) {
2992 disp = dseg_addaddress(cd, bte->fp);
2993 d = md->returntype.type;
2995 M_ALD(REG_ITMP3, REG_PV, disp); /* built-in-function pointer */
2996 M_JSR(REG_RA, REG_ITMP3);
2998 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2999 M_LDA(REG_PV, REG_RA, -disp);
3001 /* if op1 == true, we need to check for an exception */
3003 if (iptr->op1 == true) {
3004 M_BEQZ(REG_RESULT, 0);
3005 codegen_addxexceptionrefs(cd, mcodeptr);
3010 case ICMD_INVOKESPECIAL:
3011 M_BEQZ(rd->argintregs[0], 0);
3012 codegen_addxnullrefs(cd, mcodeptr);
3016 case ICMD_INVOKESTATIC:
3018 unresolved_method *um = iptr->target;
3020 disp = dseg_addaddress(cd, NULL);
3022 codegen_addpatchref(cd, mcodeptr,
3023 PATCHER_invokestatic_special, um, disp);
3025 if (opt_showdisassemble) {
3029 d = um->methodref->parseddesc.md->returntype.type;
3032 disp = dseg_addaddress(cd, lm->stubroutine);
3033 d = lm->parseddesc->returntype.type;
3036 M_ALD(REG_PV, REG_PV, disp); /* method pointer in pv */
3037 M_JSR(REG_RA, REG_PV);
3039 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3040 M_LDA(REG_PV, REG_RA, -disp);
3043 case ICMD_INVOKEVIRTUAL:
3044 gen_nullptr_check(rd->argintregs[0]);
3047 unresolved_method *um = iptr->target;
3049 codegen_addpatchref(cd, mcodeptr,
3050 PATCHER_invokevirtual, um, 0);
3052 if (opt_showdisassemble) {
3057 d = um->methodref->parseddesc.md->returntype.type;
3060 s1 = OFFSET(vftbl_t, table[0]) +
3061 sizeof(methodptr) * lm->vftblindex;
3062 d = lm->parseddesc->returntype.type;
3065 M_ALD(REG_METHODPTR, rd->argintregs[0],
3066 OFFSET(java_objectheader, vftbl));
3067 M_ALD(REG_PV, REG_METHODPTR, s1);
3068 M_JSR(REG_RA, REG_PV);
3070 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3071 M_LDA(REG_PV, REG_RA, -disp);
3074 case ICMD_INVOKEINTERFACE:
3075 gen_nullptr_check(rd->argintregs[0]);
3078 unresolved_method *um = iptr->target;
3080 codegen_addpatchref(cd, mcodeptr,
3081 PATCHER_invokeinterface, um, 0);
3083 if (opt_showdisassemble) {
3089 d = um->methodref->parseddesc.md->returntype.type;
3092 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3093 sizeof(methodptr*) * lm->class->index;
3095 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3097 d = lm->parseddesc->returntype.type;
3100 M_ALD(REG_METHODPTR, rd->argintregs[0],
3101 OFFSET(java_objectheader, vftbl));
3102 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3103 M_ALD(REG_PV, REG_METHODPTR, s2);
3104 M_JSR(REG_RA, REG_PV);
3106 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3107 M_LDA(REG_PV, REG_RA, -disp);
3111 /* d contains return type */
3113 if (d != TYPE_VOID) {
3114 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3115 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3116 M_INTMOVE(REG_RESULT, s1);
3117 store_reg_to_var_int(iptr->dst, s1);
3119 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3120 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3121 store_reg_to_var_flt(iptr->dst, s1);
3127 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3128 /* op1: 0 == array, 1 == class */
3129 /* val.a: (classinfo*) superclass */
3131 /* superclass is an interface:
3133 * OK if ((sub == NULL) ||
3134 * (sub->vftbl->interfacetablelength > super->index) &&
3135 * (sub->vftbl->interfacetable[-super->index] != NULL));
3137 * superclass is a class:
3139 * OK if ((sub == NULL) || (0
3140 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3141 * super->vftbl->diffvall));
3144 if (iptr->op1 == 1) {
3146 vftbl_t *supervftbl;
3149 super = (classinfo *) iptr->val.a;
3156 superindex = super->index;
3157 supervftbl = super->vftbl;
3160 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3161 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3164 var_to_reg_int(s1, src, REG_ITMP1);
3166 /* calculate interface checkcast code size */
3170 s2 += (opt_showdisassemble ? 2 : 0);
3172 /* calculate class checkcast code size */
3174 s3 = 10 /* 10 + (s1 == REG_ITMP1) */;
3176 s3 += (opt_showdisassemble ? 2 : 0);
3178 /* if class is not resolved, check which code to call */
3181 M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
3184 disp = dseg_adds4(cd, 0); /* super->flags */
3186 codegen_addpatchref(cd, mcodeptr,
3187 PATCHER_checkcast_instanceof_flags,
3188 (constant_classref *) iptr->target,
3191 if (opt_showdisassemble) {
3195 /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
3196 M_ILD(REG_ITMP2, REG_PV, disp);
3197 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3198 M_BEQZ(REG_ITMP2, 1 + s2 + 2);
3202 /* interface checkcast code */
3204 if (!super || super->flags & ACC_INTERFACE) {
3210 codegen_addpatchref(cd, mcodeptr,
3211 PATCHER_checkcast_instanceof_interface,
3212 (constant_classref *) iptr->target,
3215 if (opt_showdisassemble) {
3220 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3221 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3222 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3223 M_BLEZ(REG_ITMP3, 0);
3224 codegen_addxcastrefs(cd, mcodeptr);
3226 M_ALD(REG_ITMP3, REG_ITMP2,
3227 OFFSET(vftbl_t, interfacetable[0]) -
3228 superindex * sizeof(methodptr*));
3229 M_BEQZ(REG_ITMP3, 0);
3230 codegen_addxcastrefs(cd, mcodeptr);
3239 /* class checkcast code */
3241 if (!super || !(super->flags & ACC_INTERFACE)) {
3242 disp = dseg_addaddress(cd, (void *) supervftbl);
3249 codegen_addpatchref(cd, mcodeptr,
3250 PATCHER_checkcast_instanceof_class,
3251 (constant_classref *) iptr->target,
3254 if (opt_showdisassemble) {
3259 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3260 M_ALD(REG_ITMP3, REG_PV, disp);
3261 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3262 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3264 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3265 /* if (s1 != REG_ITMP1) { */
3266 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3267 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3268 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3269 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3271 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3273 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3274 M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3275 M_ALD(REG_ITMP3, REG_PV, disp);
3276 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3277 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3278 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3281 M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3282 M_BNEZ(REG_ITMP3, 0);
3283 codegen_addxcastrefs(cd, mcodeptr);
3286 d = reg_of_var(rd, iptr->dst, s1);
3289 var_to_reg_int(s1, src, rd->argintregs[0]);
3290 M_INTMOVE(s1, rd->argintregs[0]);
3292 disp = dseg_addaddress(cd, iptr->val.a);
3294 if (iptr->val.a == NULL) {
3295 codegen_addpatchref(cd, mcodeptr,
3296 PATCHER_builtin_arraycheckcast,
3297 (constant_classref *) iptr->target,
3300 if (opt_showdisassemble) {
3305 M_ALD(rd->argintregs[1], REG_PV, disp);
3306 disp = dseg_addaddress(cd, BUILTIN_arraycheckcast);
3307 M_ALD(REG_ITMP3, REG_PV, disp);
3308 M_JSR(REG_RA, REG_ITMP3);
3311 M_BEQZ(REG_RESULT, 0);
3312 codegen_addxcastrefs(cd, mcodeptr);
3315 var_to_reg_int(s1, src, REG_ITMP1);
3316 d = reg_of_var(rd, iptr->dst, s1);
3319 store_reg_to_var_int(iptr->dst, d);
3322 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3323 /* op1: 0 == array, 1 == class */
3324 /* val.a: (classinfo*) superclass */
3326 /* superclass is an interface:
3328 * return (sub != NULL) &&
3329 * (sub->vftbl->interfacetablelength > super->index) &&
3330 * (sub->vftbl->interfacetable[-super->index] != NULL);
3332 * superclass is a class:
3334 * return ((sub != NULL) && (0
3335 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3336 * super->vftbl->diffvall));
3341 vftbl_t *supervftbl;
3344 super = (classinfo *) iptr->val.a;
3351 superindex = super->index;
3352 supervftbl = super->vftbl;
3355 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3356 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3359 var_to_reg_int(s1, src, REG_ITMP1);
3360 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3362 M_MOV(s1, REG_ITMP1);
3366 /* calculate interface instanceof code size */
3370 s2 += (opt_showdisassemble ? 2 : 0);
3372 /* calculate class instanceof code size */
3376 s3 += (opt_showdisassemble ? 2 : 0);
3380 /* if class is not resolved, check which code to call */
3383 M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
3386 disp = dseg_adds4(cd, 0); /* super->flags */
3388 codegen_addpatchref(cd, mcodeptr,
3389 PATCHER_checkcast_instanceof_flags,
3390 (constant_classref *) iptr->target, disp);
3392 if (opt_showdisassemble) {
3396 /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
3397 M_ILD(REG_ITMP3, REG_PV, disp);
3398 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
3399 M_BEQZ(REG_ITMP3, 1 + s2 + 2);
3403 /* interface instanceof code */
3405 if (!super || (super->flags & ACC_INTERFACE)) {
3411 codegen_addpatchref(cd, mcodeptr,
3412 PATCHER_checkcast_instanceof_interface,
3413 (constant_classref *) iptr->target, 0);
3415 if (opt_showdisassemble) {
3420 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3421 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3422 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3423 M_BLEZ(REG_ITMP3, 3);
3425 M_ALD(REG_ITMP1, REG_ITMP1,
3426 OFFSET(vftbl_t, interfacetable[0]) -
3427 superindex * sizeof(methodptr*));
3428 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3436 /* class instanceof code */
3438 if (!super || !(super->flags & ACC_INTERFACE)) {
3439 disp = dseg_addaddress(cd, supervftbl);
3446 codegen_addpatchref(cd, mcodeptr,
3447 PATCHER_checkcast_instanceof_class,
3448 (constant_classref *) iptr->target,
3451 if (opt_showdisassemble) {
3456 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3457 M_ALD(REG_ITMP2, REG_PV, disp);
3458 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3459 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3461 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3462 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3463 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3464 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3465 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3467 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3468 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3471 store_reg_to_var_int(iptr->dst, d);
3475 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3476 /* op1 = dimension, val.a = array descriptor */
3478 /* check for negative sizes and copy sizes to stack if necessary */
3480 MCODECHECK((iptr->op1 << 1) + 64);
3482 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3483 /* copy SAVEDVAR sizes to stack */
3485 if (src->varkind != ARGVAR) {
3486 var_to_reg_int(s2, src, REG_ITMP1);
3487 M_LST(s2, REG_SP, s1 * 8);
3491 /* a0 = dimension count */
3493 ICONST(rd->argintregs[0], iptr->op1);
3495 /* is patcher function set? */
3498 disp = dseg_addaddress(cd, NULL);
3500 codegen_addpatchref(cd, mcodeptr,
3501 PATCHER_builtin_multianewarray,
3504 if (opt_showdisassemble) {
3509 disp = dseg_addaddress(cd, iptr->val.a);
3512 /* a1 = arraydescriptor */
3514 M_ALD(rd->argintregs[1], REG_PV, disp);
3516 /* a2 = pointer to dimensions = stack pointer */
3518 M_INTMOVE(REG_SP, rd->argintregs[2]);
3520 disp = dseg_addaddress(cd, BUILTIN_multianewarray);
3521 M_ALD(REG_ITMP3, REG_PV, disp);
3522 M_JSR(REG_RA, REG_ITMP3);
3525 /* check for exception before result assignment */
3527 M_BEQZ(REG_RESULT, 0);
3528 codegen_addxexceptionrefs(cd, mcodeptr);
3531 d = reg_of_var(rd, iptr->dst, REG_RESULT);
3532 M_INTMOVE(REG_RESULT, d);
3533 store_reg_to_var_int(iptr->dst, d);
3537 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3541 } /* for instruction */
3543 /* copy values to interface registers */
3545 src = bptr->outstack;
3546 len = bptr->outdepth;
3553 if ((src->varkind != STACKVAR)) {
3555 if (IS_FLT_DBL_TYPE(s2)) {
3556 var_to_reg_flt(s1, src, REG_FTMP1);
3557 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3558 M_TFLTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3561 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3565 var_to_reg_int(s1, src, REG_ITMP1);
3566 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3567 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3570 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3577 /* At the end of a basic block we may have to append some nops,
3578 because the patcher stub calling code might be longer than the
3579 actual instruction. So codepatching does not change the
3580 following block unintentionally. */
3582 if ((u1 *) mcodeptr < cd->lastmcodeptr) {
3583 while ((u1 *) mcodeptr < cd->lastmcodeptr) {
3588 } /* if (bptr -> flags >= BBREACHED) */
3589 } /* for basic block */
3591 codegen_createlinenumbertable(cd);
3597 /* generate ArithmeticException stubs */
3601 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3602 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3604 (u1 *) mcodeptr - cd->mcodebase);
3608 if (xcodeptr != NULL) {
3609 M_BR(xcodeptr - mcodeptr);
3610 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3613 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3615 xcodeptr = mcodeptr;
3617 M_MOV(REG_PV, rd->argintregs[0]);
3618 M_MOV(REG_SP, rd->argintregs[1]);
3620 if (m->isleafmethod)
3621 M_MOV(REG_RA, rd->argintregs[2]);
3623 M_ALD(rd->argintregs[2],
3624 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3626 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3628 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3629 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3631 if (m->isleafmethod)
3632 M_AST(REG_RA, REG_SP, 1 * 8);
3634 a = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
3635 M_ALD(REG_ITMP3, REG_PV, a);
3636 M_JSR(REG_RA, REG_ITMP3);
3638 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3640 if (m->isleafmethod)
3641 M_ALD(REG_RA, REG_SP, 1 * 8);
3643 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3644 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3646 a = dseg_addaddress(cd, asm_handle_exception);
3647 M_ALD(REG_ITMP3, REG_PV, a);
3653 /* generate ArrayIndexOutOfBoundsException stubs */
3657 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3658 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3660 (u1 *) mcodeptr - cd->mcodebase);
3664 /* move index register into REG_ITMP1 */
3666 M_MOV(bref->reg, REG_ITMP1);
3667 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3669 if (xcodeptr != NULL) {
3670 M_BR(xcodeptr - mcodeptr);
3674 xcodeptr = mcodeptr;
3676 M_MOV(REG_PV, rd->argintregs[0]);
3677 M_MOV(REG_SP, rd->argintregs[1]);
3679 if (m->isleafmethod)
3680 M_MOV(REG_RA, rd->argintregs[2]);
3682 M_ALD(rd->argintregs[2],
3683 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3685 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3686 M_MOV(REG_ITMP1, rd->argintregs[4]);
3688 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3689 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3691 if (m->isleafmethod)
3692 M_AST(REG_RA, REG_SP, 1 * 8);
3694 a = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
3695 M_ALD(REG_ITMP3, REG_PV, a);
3696 M_JSR(REG_RA, REG_ITMP3);
3698 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3700 if (m->isleafmethod)
3701 M_ALD(REG_RA, REG_SP, 1 * 8);
3703 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3704 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3706 a = dseg_addaddress(cd, asm_handle_exception);
3707 M_ALD(REG_ITMP3, REG_PV, a);
3713 /* generate ArrayStoreException stubs */
3717 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
3718 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3720 (u1 *) mcodeptr - cd->mcodebase);
3724 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3726 if (xcodeptr != NULL) {
3727 M_BR(xcodeptr - mcodeptr);
3731 xcodeptr = mcodeptr;
3733 M_MOV(REG_PV, rd->argintregs[0]);
3734 M_MOV(REG_SP, rd->argintregs[1]);
3735 M_ALD(rd->argintregs[2],
3736 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3737 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3739 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3740 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3742 a = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
3743 M_ALD(REG_ITMP3, REG_PV, a);
3744 M_JSR(REG_RA, REG_ITMP3);
3746 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3748 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3749 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3751 a = dseg_addaddress(cd, asm_handle_exception);
3752 M_ALD(REG_ITMP3, REG_PV, a);
3758 /* generate ClassCastException stubs */
3762 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3763 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3765 (u1 *) mcodeptr - cd->mcodebase);
3769 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3771 if (xcodeptr != NULL) {
3772 M_BR(xcodeptr - mcodeptr);
3776 xcodeptr = mcodeptr;
3778 M_MOV(REG_PV, rd->argintregs[0]);
3779 M_MOV(REG_SP, rd->argintregs[1]);
3781 if (m->isleafmethod)
3782 M_MOV(REG_RA, rd->argintregs[2]);
3784 M_ALD(rd->argintregs[2],
3785 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3787 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3789 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3790 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3792 if (m->isleafmethod)
3793 M_AST(REG_RA, REG_SP, 1 * 8);
3795 a = dseg_addaddress(cd, stacktrace_inline_classcastexception);
3796 M_ALD(REG_ITMP3, REG_PV, a);
3797 M_JSR(REG_RA, REG_ITMP3);
3799 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3801 if (m->isleafmethod)
3802 M_ALD(REG_RA, REG_SP, 1 * 8);
3804 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3805 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3807 a = dseg_addaddress(cd, asm_handle_exception);
3808 M_ALD(REG_ITMP3, REG_PV, a);
3814 /* generate NullPointerException stubs */
3818 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3819 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3821 (u1 *) mcodeptr - cd->mcodebase);
3825 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3827 if (xcodeptr != NULL) {
3828 M_BR(xcodeptr - mcodeptr);
3832 xcodeptr = mcodeptr;
3834 M_MOV(REG_PV, rd->argintregs[0]);
3835 M_MOV(REG_SP, rd->argintregs[1]);
3837 if (m->isleafmethod)
3838 M_MOV(REG_RA, rd->argintregs[2]);
3840 M_ALD(rd->argintregs[2],
3841 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3843 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3845 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3846 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3848 if (m->isleafmethod)
3849 M_AST(REG_RA, REG_SP, 1 * 8);
3851 a = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
3852 M_ALD(REG_ITMP3, REG_PV, a);
3853 M_JSR(REG_RA, REG_ITMP3);
3855 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3857 if (m->isleafmethod)
3858 M_ALD(REG_RA, REG_SP, 1 * 8);
3860 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3861 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3863 a = dseg_addaddress(cd, asm_handle_exception);
3864 M_ALD(REG_ITMP3, REG_PV, a);
3870 /* generate exception check stubs */
3874 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3875 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3877 (u1 *) mcodeptr - cd->mcodebase);
3881 if (xcodeptr != NULL) {
3882 M_BR(xcodeptr - mcodeptr);
3883 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3886 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3888 xcodeptr = mcodeptr;
3890 M_MOV(REG_PV, rd->argintregs[0]);
3891 M_MOV(REG_SP, rd->argintregs[1]);
3892 M_ALD(rd->argintregs[2],
3893 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3894 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3896 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3897 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3899 a = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
3900 M_ALD(REG_ITMP3, REG_PV, a);
3901 M_JSR(REG_RA, REG_ITMP3);
3903 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3905 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3906 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3908 a = dseg_addaddress(cd, asm_handle_exception);
3909 M_ALD(REG_ITMP3, REG_PV, a);
3915 /* generate patcher stub call code */
3922 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3923 /* check code segment size */
3927 /* Get machine code which is patched back in later. The call is */
3928 /* 2 instruction words long. */
3930 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3932 /* We need to split this, because an unaligned 8 byte read causes */
3935 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3937 /* patch in the call to call the following code (done at compile */
3940 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3941 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3943 disp = (s4) (tmpmcodeptr - (xcodeptr + 1));
3945 if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) {
3947 new_internalerror("Jump offset is out of range: %d > +/-%d",
3955 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3957 /* create stack frame */
3959 M_ASUB_IMM(REG_SP, 6 * 8, REG_SP);
3961 /* calculate return address and move it onto the stack */
3963 M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
3964 M_AST(REG_ITMP3, REG_SP, 5 * 8);
3966 /* move pointer to java_objectheader onto stack */
3968 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3969 /* create a virtual java_objectheader */
3971 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3972 disp = dseg_addaddress(cd, NULL); /* vftbl */
3974 M_LDA(REG_ITMP3, REG_PV, disp);
3975 M_AST(REG_ITMP3, REG_SP, 4 * 8);
3980 /* move machine code onto stack */
3982 disp = dseg_adds8(cd, mcode);
3983 M_LLD(REG_ITMP3, REG_PV, disp);
3984 M_LST(REG_ITMP3, REG_SP, 3 * 8);
3986 /* move class/method/field reference onto stack */
3988 disp = dseg_addaddress(cd, pref->ref);
3989 M_ALD(REG_ITMP3, REG_PV, disp);
3990 M_AST(REG_ITMP3, REG_SP, 2 * 8);
3992 /* move data segment displacement onto stack */
3994 disp = dseg_adds4(cd, pref->disp);
3995 M_ILD(REG_ITMP3, REG_PV, disp);
3996 M_IST(REG_ITMP3, REG_SP, 1 * 8);
3998 /* move patcher function pointer onto stack */
4000 disp = dseg_addaddress(cd, pref->patcher);
4001 M_ALD(REG_ITMP3, REG_PV, disp);
4002 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4004 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4005 M_ALD(REG_ITMP3, REG_PV, disp);
4012 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4014 docacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4016 /* everything's ok */
4022 /* createcompilerstub **********************************************************
4024 Creates a stub routine which calls the compiler.
4026 *******************************************************************************/
4028 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
4029 #define COMPILERSTUB_CODESIZE 4 * 4
4031 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4034 u1 *createcompilerstub(methodinfo *m)
4036 ptrint *s; /* memory to hold the stub */
4037 s4 *mcodeptr; /* code generation pointer */
4039 s = (ptrint *) CNEW(u1, COMPILERSTUB_SIZE);
4042 s[1] = (ptrint) asm_call_jit_compiler;
4044 mcodeptr = (s4 *) (s + 2);
4046 M_ALD(REG_ITMP1, REG_PV, -2 * SIZEOF_VOID_P); /* method pointer */
4047 M_ALD(REG_PV, REG_PV, -1 * SIZEOF_VOID_P); /* pointer to compiler */
4051 (void) docacheflush((void *) s, (char *) mcodeptr - (char *) s);
4053 #if defined(STATISTICS)
4055 count_cstub_len += COMPILERSTUB_SIZE;
4058 return (((u1 *) s) + COMPILERSTUB_DATASIZE);
4062 /* createnativestub ************************************************************
4064 Creates a stub routine which calls a native method.
4066 *******************************************************************************/
4068 u1 *createnativestub(functionptr f, methodinfo *m, codegendata *cd,
4069 registerdata *rd, methoddesc *nmd)
4071 s4 *mcodeptr; /* code generation pointer */
4072 s4 stackframesize; /* size of stackframe if needed */
4075 s4 i, j; /* count variables */
4078 s4 funcdisp; /* displacement of the function */
4081 /* initialize variables */
4084 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4087 /* calculate stack frame size */
4090 1 + /* return address */
4091 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4092 sizeof(localref_table) / SIZEOF_VOID_P +
4093 md->paramcount + /* for saving arguments over calls */
4094 1 + /* for saving return address */
4098 /* create method header */
4100 #if SIZEOF_VOID_P == 4
4101 (void) dseg_addaddress(cd, m); /* MethodPointer */
4103 (void) dseg_addaddress(cd, m); /* MethodPointer */
4104 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4105 (void) dseg_adds4(cd, 0); /* IsSync */
4106 (void) dseg_adds4(cd, 0); /* IsLeaf */
4107 (void) dseg_adds4(cd, 0); /* IntSave */
4108 (void) dseg_adds4(cd, 0); /* FltSave */
4109 (void) dseg_addlinenumbertablesize(cd);
4110 (void) dseg_adds4(cd, 0); /* ExTableSize */
4113 /* initialize mcode variables */
4115 mcodeptr = (s4 *) cd->mcodebase;
4116 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
4119 /* generate stub code */
4121 M_LDA(REG_SP, REG_SP, -stackframesize * 8); /* build up stackframe */
4122 M_AST(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* store ra */
4125 /* call trace function */
4128 M_LDA(REG_SP, REG_SP, -(1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4130 /* save integer argument registers */
4132 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4133 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4134 M_LST(rd->argintregs[i], REG_SP, (1 + i) * 8);
4136 /* save and copy float arguments into integer registers */
4138 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4139 t = md->paramtypes[i].type;
4141 if (IS_FLT_DBL_TYPE(t)) {
4142 if (IS_2_WORD_TYPE(t)) {
4143 M_DST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4144 M_LLD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4146 M_FST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4147 M_ILD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4152 disp = dseg_addaddress(cd, m);
4153 M_ALD(REG_ITMP1, REG_PV, disp);
4154 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4155 disp = dseg_addaddress(cd, builtin_trace_args);
4156 M_ALD(REG_ITMP3, REG_PV, disp);
4157 M_JSR(REG_RA, REG_ITMP3);
4160 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4161 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4162 M_LLD(rd->argintregs[i], REG_SP, (1 + i) * 8);
4164 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4165 t = md->paramtypes[i].type;
4167 if (IS_FLT_DBL_TYPE(t)) {
4168 if (IS_2_WORD_TYPE(t)) {
4169 M_DLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4171 M_FLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4176 M_LDA(REG_SP, REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4180 /* get function address (this must happen before the stackframeinfo) */
4182 funcdisp = dseg_addaddress(cd, f);
4184 #if !defined(ENABLE_STATICVM)
4186 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m, funcdisp);
4188 if (opt_showdisassemble) {
4194 /* save integer and float argument registers */
4196 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4197 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4198 M_LST(rd->argintregs[i], REG_SP, j * 8);
4203 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4204 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4205 M_DST(rd->argfltregs[i], REG_SP, j * 8);
4210 /* prepare data structures for native function call */
4212 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4213 M_MOV(REG_PV, rd->argintregs[1]);
4214 M_AADD_IMM(REG_SP, stackframesize * 8, rd->argintregs[2]);
4215 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8 - SIZEOF_VOID_P);
4216 disp = dseg_addaddress(cd, codegen_start_native_call);
4217 M_ALD(REG_ITMP3, REG_PV, disp);
4218 M_JSR(REG_RA, REG_ITMP3);
4219 M_NOP; /* XXX fill me! */
4221 /* restore integer and float argument registers */
4223 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4224 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4225 M_LLD(rd->argintregs[i], REG_SP, j * 8);
4230 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4231 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4232 M_DLD(rd->argfltregs[i], REG_SP, j * 8);
4237 /* copy or spill arguments to new locations */
4239 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4240 t = md->paramtypes[i].type;
4242 if (IS_INT_LNG_TYPE(t)) {
4243 if (!md->params[i].inmemory) {
4244 s1 = rd->argintregs[md->params[i].regoff];
4246 if (!nmd->params[j].inmemory) {
4247 s2 = rd->argintregs[nmd->params[j].regoff];
4250 s2 = nmd->params[j].regoff;
4251 M_AST(s1, REG_SP, s2 * 8);
4255 s1 = md->params[i].regoff + stackframesize;
4256 s2 = nmd->params[j].regoff;
4257 M_ALD(REG_ITMP1, REG_SP, s1 * 8);
4258 M_AST(REG_ITMP1, REG_SP, s2 * 8);
4262 if (!md->params[i].inmemory) {
4263 s1 = rd->argfltregs[md->params[i].regoff];
4265 if (!nmd->params[j].inmemory) {
4266 s2 = rd->argfltregs[nmd->params[j].regoff];
4267 M_TFLTMOVE(t, s1, s2);
4269 s2 = nmd->params[j].regoff;
4270 if (IS_2_WORD_TYPE(t))
4271 M_DST(s1, REG_SP, s2 * 8);
4273 M_FST(s1, REG_SP, s2 * 8);
4277 s1 = md->params[i].regoff + stackframesize;
4278 s2 = nmd->params[j].regoff;
4279 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4280 if (IS_2_WORD_TYPE(t))
4281 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4283 M_FST(REG_FTMP1, REG_SP, s2 * 8);
4288 /* put class into second argument register */
4290 if (m->flags & ACC_STATIC) {
4291 disp = dseg_addaddress(cd, m->class);
4292 M_ALD(rd->argintregs[1], REG_PV, disp);
4295 /* put env into first argument register */
4297 disp = dseg_addaddress(cd, &env);
4298 M_ALD(rd->argintregs[0], REG_PV, disp);
4300 /* do the native function call */
4302 M_ALD(REG_ITMP3, REG_PV, funcdisp); /* load adress of native method */
4303 M_JSR(REG_RA, REG_ITMP3); /* call native method */
4304 M_NOP; /* delay slot */
4306 /* save return value */
4308 if (IS_INT_LNG_TYPE(md->returntype.type))
4309 M_LST(REG_RESULT, REG_SP, 0 * 8);
4311 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4313 /* remove native stackframe info */
4315 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4316 disp = dseg_addaddress(cd, codegen_finish_native_call);
4317 M_ALD(REG_ITMP3, REG_PV, disp);
4318 M_JSR(REG_RA, REG_ITMP3);
4319 M_NOP; /* XXX fill me! */
4321 /* call finished trace function */
4324 if (IS_INT_LNG_TYPE(md->returntype.type))
4325 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4327 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4329 disp = dseg_addaddress(cd, m);
4330 M_ALD(rd->argintregs[0], REG_PV, disp);
4332 M_MOV(REG_RESULT, rd->argintregs[1]);
4333 M_DMFC1(REG_ITMP1, REG_FRESULT);
4334 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4335 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4337 disp = dseg_addaddress(cd, builtin_displaymethodstop);
4338 M_ALD(REG_ITMP3, REG_PV, disp);
4339 M_JSR(REG_RA, REG_ITMP3);
4343 /* check for exception */
4345 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4346 disp = dseg_addaddress(cd, builtin_get_exceptionptrptr);
4347 M_ALD(REG_ITMP3, REG_PV, disp);
4348 M_JSR(REG_RA, REG_ITMP3);
4350 M_MOV(REG_RESULT, REG_ITMP3);
4352 disp = dseg_addaddress(cd, &_exceptionptr);
4353 M_ALD(REG_ITMP3, REG_PV, disp); /* get address of exceptionptr */
4355 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4357 M_ALD(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* load ra */
4359 /* restore return value */
4361 if (IS_INT_LNG_TYPE(md->returntype.type))
4362 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4364 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4366 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
4367 M_LDA(REG_SP, REG_SP, stackframesize * 8);/* remove stackframe, DELAY SLOT*/
4369 M_RET(REG_RA); /* return to caller */
4370 M_NOP; /* DELAY SLOT */
4372 /* handle exception */
4374 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4376 disp = dseg_addaddress(cd, asm_handle_nat_exception);
4377 M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */
4378 M_JMP(REG_ITMP3); /* jump to asm exception handler */
4379 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4382 /* generate static stub call code */
4390 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4391 /* Get machine code which is patched back in later. The call is */
4392 /* 2 instruction words long. */
4394 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4396 /* We need to split this, because an unaligned 8 byte read causes */
4399 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
4401 /* patch in the call to call the following code (done at compile */
4404 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4405 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4407 M_BRS(tmpmcodeptr - (xcodeptr + 1));
4408 M_NOP; /* branch delay slot */
4410 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4412 /* create stack frame */
4414 M_LSUB_IMM(REG_SP, 6 * 8, REG_SP);
4416 /* move return address onto stack */
4418 M_AST(REG_RA, REG_SP, 5 * 8);
4420 /* move pointer to java_objectheader onto stack */
4422 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4423 /* order reversed because of data segment layout */
4425 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4426 disp = dseg_addaddress(cd, NULL); /* vftbl */
4428 M_LDA(REG_ITMP3, REG_PV, disp);
4429 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4431 M_AST(REG_ZERO, REG_SP, 4 * 8);
4434 /* move machine code onto stack */
4436 disp = dseg_adds8(cd, mcode);
4437 M_LLD(REG_ITMP3, REG_PV, disp);
4438 M_LST(REG_ITMP3, REG_SP, 3 * 8);
4440 /* move class/method/field reference onto stack */
4442 disp = dseg_addaddress(cd, pref->ref);
4443 M_ALD(REG_ITMP3, REG_PV, disp);
4444 M_AST(REG_ITMP3, REG_SP, 2 * 8);
4446 /* move data segment displacement onto stack */
4448 disp = dseg_adds4(cd, pref->disp);
4449 M_ILD(REG_ITMP3, REG_PV, disp);
4450 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4452 /* move patcher function pointer onto stack */
4454 disp = dseg_addaddress(cd, pref->patcher);
4455 M_ALD(REG_ITMP3, REG_PV, disp);
4456 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4458 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4459 M_ALD(REG_ITMP3, REG_PV, disp);
4465 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4467 docacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4469 return m->entrypoint;
4474 * These are local overrides for various environment variables in Emacs.
4475 * Please do not remove this and leave it at the end of the file, where
4476 * Emacs will automagically detect them.
4477 * ---------------------------------------------------------------------
4480 * indent-tabs-mode: t