1 /* src/vm/jit/mips/codegen.c - machine code generator for MIPS
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Andreas Krall
30 Changes: Christian Thalinger
34 Contains the codegenerator for an MIPS (R4000 or higher) processor.
35 This module generates MIPS machine code for a sequence of
36 intermediate code commands (ICMDs).
38 $Id: codegen.c 4654 2006-03-19 19:46:11Z edwin $
53 #include "vm/jit/mips/arch.h"
54 #include "vm/jit/mips/codegen.h"
56 #include "native/native.h"
57 #include "vm/builtin.h"
59 #include "vm/exceptions.h"
60 #include "vm/options.h"
61 #include "vm/stringlocal.h"
63 #include "vm/jit/asmpart.h"
64 #include "vm/jit/codegen-common.h"
65 #include "vm/jit/dseg.h"
66 #include "vm/jit/jit.h"
67 #include "vm/jit/patcher.h"
68 #include "vm/jit/reg.h"
69 #include "vm/jit/replace.h"
71 #if defined(ENABLE_LSRA)
72 # include "vm/jit/allocator/lsra.h"
76 /* codegen *********************************************************************
78 Generates machine code.
80 *******************************************************************************/
82 bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
84 s4 len, s1, s2, s3, d, disp;
94 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
95 builtintable_entry *bte;
97 rplpoint *replacementpoint;
103 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
105 /* space to save used callee saved registers */
107 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
108 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
110 parentargs_base = rd->memuse + savedregs_num;
112 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
113 if (checksync && (m->flags & ACC_SYNCHRONIZED))
117 /* adjust frame size for 16 byte alignment */
119 if (parentargs_base & 1)
122 /* create method header */
124 #if SIZEOF_VOID_P == 4
125 (void) dseg_addaddress(cd, m); /* Filler */
127 (void) dseg_addaddress(cd, m); /* MethodPointer */
128 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
130 #if defined(USE_THREADS)
131 /* IsSync contains the offset relative to the stack pointer for the
132 argument of monitor_exit used in the exception handler. Since the
133 offset could be zero and give a wrong meaning of the flag it is
137 if (checksync && (m->flags & ACC_SYNCHRONIZED))
138 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
141 (void) dseg_adds4(cd, 0); /* IsSync */
143 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
144 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
145 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
146 dseg_addlinenumbertablesize(cd);
147 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
149 /* create exception table */
151 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
152 dseg_addtarget(cd, ex->start);
153 dseg_addtarget(cd, ex->end);
154 dseg_addtarget(cd, ex->handler);
155 (void) dseg_addaddress(cd, ex->catchtype.cls);
158 /* initialize mcode variables */
160 mcodeptr = (s4 *) cd->mcodeptr;
162 /* initialize the last patcher pointer */
164 cd->lastmcodeptr = (u1 *) mcodeptr;
166 /* create stack frame (if necessary) */
169 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
171 /* save return address and used callee saved registers */
174 if (!m->isleafmethod) {
175 p--; M_AST(REG_RA, REG_SP, p * 8);
177 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
178 p--; M_AST(rd->savintregs[i], REG_SP, p * 8);
180 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
181 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
184 /* take arguments out of register or stack frame */
188 for (p = 0, l = 0; p < md->paramcount; p++) {
189 t = md->paramtypes[p].type;
190 var = &(rd->locals[l][t]);
192 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
196 s1 = md->params[p].regoff;
197 if (IS_INT_LNG_TYPE(t)) { /* integer args */
198 if (!md->params[p].inmemory) { /* register arguments */
199 s2 = rd->argintregs[s1];
200 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
201 M_INTMOVE(s2, var->regoff);
202 } else { /* reg arg -> spilled */
203 M_LST(s2, REG_SP, var->regoff * 8);
206 } else { /* stack arguments */
207 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
208 M_LLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
209 } else { /* stack arg -> spilled */
210 var->regoff = parentargs_base + s1;
214 } else { /* floating args */
215 if (!md->params[p].inmemory) { /* register arguments */
216 s2 = rd->argfltregs[s1];
217 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
218 M_TFLTMOVE(var->type, s2, var->regoff);
219 } else { /* reg arg -> spilled */
220 M_DST(s2, REG_SP, var->regoff * 8);
223 } else { /* stack arguments */
224 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
225 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
226 } else { /* stack-arg -> spilled */
227 var->regoff = parentargs_base + s1;
233 /* call monitorenter function */
235 #if defined(USE_THREADS)
236 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
237 /* stack offset for monitor argument */
241 if (opt_verbosecall) {
242 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
244 for (p = 0; p < INT_ARG_CNT; p++)
245 M_LST(rd->argintregs[p], REG_SP, p * 8);
247 for (p = 0; p < FLT_ARG_CNT; p++)
248 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
250 s1 += INT_ARG_CNT + FLT_ARG_CNT;
253 /* decide which monitor enter function to call */
255 if (m->flags & ACC_STATIC) {
256 p = dseg_addaddress(cd, m->class);
257 M_ALD(rd->argintregs[0], REG_PV, p);
258 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
259 M_ALD(REG_ITMP3, REG_PV, p);
260 M_JSR(REG_RA, REG_ITMP3);
261 M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* branch delay */
264 M_BEQZ(rd->argintregs[0], 0);
265 codegen_add_nullpointerexception_ref(cd, mcodeptr);
266 p = dseg_addaddress(cd, BUILTIN_monitorenter);
267 M_ALD(REG_ITMP3, REG_PV, p);
268 M_JSR(REG_RA, REG_ITMP3);
269 M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* branch delay */
272 if (opt_verbosecall) {
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 */
287 if (opt_verbosecall) {
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 replacementpoint = cd->code->rplpoints;
378 /* walk through all basic blocks */
380 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
382 /* handle replacement points */
384 if (bptr->bitflags & BBFLAG_REPLACEMENT && bptr->flags >= BBREACHED) {
386 /* 8-byte align pc */
387 if ((ptrint)mcodeptr & 4) {
391 replacementpoint->pc = (u1*)(ptrint)((u1*)mcodeptr - cd->mcodebase);
394 assert(cd->lastmcodeptr <= (u1*)mcodeptr);
395 cd->lastmcodeptr = (u1*)cd->mcodeptr + 2*4; /* br + delay slot */
398 /* store relative start of block */
400 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
402 if (bptr->flags >= BBREACHED) {
404 /* branch resolving */
407 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
408 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
414 /* copy interface registers to their destination */
419 #if defined(ENABLE_LSRA)
421 while (src != NULL) {
423 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
424 /* d = reg_of_var(m, src, REG_ITMP1); */
425 if (!(src->flags & INMEMORY))
429 M_INTMOVE(REG_ITMP1, d);
430 store_reg_to_var_int(src, d);
436 while (src != NULL) {
438 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
439 d = reg_of_var(rd, src, REG_ITMP1);
440 M_INTMOVE(REG_ITMP1, d);
441 store_reg_to_var_int(src, d);
444 d = reg_of_var(rd, src, REG_IFTMP);
445 if ((src->varkind != STACKVAR)) {
447 if (IS_FLT_DBL_TYPE(s2)) {
448 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
449 s1 = rd->interfaces[len][s2].regoff;
450 M_TFLTMOVE(s2, s1, d);
453 M_DLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
455 store_reg_to_var_flt(src, d);
458 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
459 s1 = rd->interfaces[len][s2].regoff;
463 M_LLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
465 store_reg_to_var_int(src, d);
471 #if defined(ENABLE_LSRA)
474 /* walk through all instructions */
480 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
481 if (iptr->line != currentline) {
482 dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
483 currentline = iptr->line;
486 MCODECHECK(64); /* an instruction usually needs < 64 words */
490 case ICMD_NOP: /* ... ==> ... */
493 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
495 var_to_reg_int(s1, src, REG_ITMP1);
497 codegen_add_nullpointerexception_ref(cd, mcodeptr);
501 /* constant operations ************************************************/
503 case ICMD_ICONST: /* ... ==> ..., constant */
504 /* op1 = 0, val.i = constant */
506 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
507 ICONST(d, iptr->val.i);
508 store_reg_to_var_int(iptr->dst, d);
511 case ICMD_LCONST: /* ... ==> ..., constant */
512 /* op1 = 0, val.l = constant */
514 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
515 LCONST(d, iptr->val.l);
516 store_reg_to_var_int(iptr->dst, d);
519 case ICMD_FCONST: /* ... ==> ..., constant */
520 /* op1 = 0, val.f = constant */
522 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
523 disp = dseg_addfloat(cd, iptr->val.f);
524 M_FLD(d, REG_PV, disp);
525 store_reg_to_var_flt(iptr->dst, d);
528 case ICMD_DCONST: /* ... ==> ..., constant */
529 /* op1 = 0, val.d = constant */
531 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
532 disp = dseg_adddouble(cd, iptr->val.d);
533 M_DLD(d, REG_PV, disp);
534 store_reg_to_var_flt (iptr->dst, d);
537 case ICMD_ACONST: /* ... ==> ..., constant */
538 /* op1 = 0, val.a = constant */
540 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
542 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
543 disp = dseg_addaddress(cd, iptr->val.a);
545 codegen_addpatchref(cd, mcodeptr,
547 (unresolved_class *) iptr->target, disp);
549 if (opt_showdisassemble) {
553 M_ALD(d, REG_PV, disp);
556 if (iptr->val.a == NULL) {
557 M_INTMOVE(REG_ZERO, d);
559 disp = dseg_addaddress(cd, iptr->val.a);
560 M_ALD(d, REG_PV, disp);
563 store_reg_to_var_int(iptr->dst, d);
567 /* load/store operations **********************************************/
569 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
570 case ICMD_LLOAD: /* op1 = local variable */
573 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
574 if ((iptr->dst->varkind == LOCALVAR) &&
575 (iptr->dst->varnum == iptr->op1))
577 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
578 if (var->flags & INMEMORY) {
579 M_LLD(d, REG_SP, 8 * var->regoff);
581 M_INTMOVE(var->regoff,d);
583 store_reg_to_var_int(iptr->dst, d);
586 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
587 case ICMD_DLOAD: /* op1 = local variable */
589 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
590 if ((iptr->dst->varkind == LOCALVAR) &&
591 (iptr->dst->varnum == iptr->op1))
593 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
595 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
596 if (var->flags & INMEMORY) {
597 M_CCFLD(var->type, t2, d, REG_SP, 8 * var->regoff);
599 M_CCFLTMOVE(var->type, t2, var->regoff, d);
602 store_reg_to_var_flt(iptr->dst, d);
606 case ICMD_ISTORE: /* ..., value ==> ... */
607 case ICMD_LSTORE: /* op1 = local variable */
610 if ((src->varkind == LOCALVAR) &&
611 (src->varnum == iptr->op1))
613 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
614 if (var->flags & INMEMORY) {
615 var_to_reg_int(s1, src, REG_ITMP1);
616 M_LST(s1, REG_SP, 8 * var->regoff);
619 var_to_reg_int(s1, src, var->regoff);
620 M_INTMOVE(s1, var->regoff);
624 case ICMD_FSTORE: /* ..., value ==> ... */
625 case ICMD_DSTORE: /* op1 = local variable */
627 if ((src->varkind == LOCALVAR) &&
628 (src->varnum == iptr->op1))
630 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
632 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
633 if (var->flags & INMEMORY) {
634 var_to_reg_flt(s1, src, REG_FTMP1);
635 M_CCFST(t1, var->type, s1, REG_SP, 8 * var->regoff);
638 var_to_reg_flt(s1, src, var->regoff);
639 M_CCFLTMOVE(t1, var->type, s1, var->regoff);
645 /* pop/dup/swap operations ********************************************/
647 /* attention: double and longs are only one entry in CACAO ICMDs */
649 case ICMD_POP: /* ..., value ==> ... */
650 case ICMD_POP2: /* ..., value, value ==> ... */
653 case ICMD_DUP: /* ..., a ==> ..., a, a */
654 M_COPY(src, iptr->dst);
657 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
659 M_COPY(src, iptr->dst);
660 M_COPY(src->prev, iptr->dst->prev);
661 M_COPY(iptr->dst, iptr->dst->prev->prev);
664 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
666 M_COPY(src, iptr->dst);
667 M_COPY(src->prev, iptr->dst->prev);
668 M_COPY(src->prev->prev, iptr->dst->prev->prev);
669 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
672 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
674 M_COPY(src, iptr->dst);
675 M_COPY(src->prev, iptr->dst->prev);
678 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
680 M_COPY(src, iptr->dst);
681 M_COPY(src->prev, iptr->dst->prev);
682 M_COPY(src->prev->prev, iptr->dst->prev->prev);
683 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
684 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
687 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
689 M_COPY(src, iptr->dst);
690 M_COPY(src->prev, iptr->dst->prev);
691 M_COPY(src->prev->prev, iptr->dst->prev->prev);
692 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
693 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
694 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
697 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
699 M_COPY(src, iptr->dst->prev);
700 M_COPY(src->prev, iptr->dst);
704 /* integer operations *************************************************/
706 case ICMD_INEG: /* ..., value ==> ..., - value */
708 var_to_reg_int(s1, src, REG_ITMP1);
709 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
710 M_ISUB(REG_ZERO, s1, d);
711 store_reg_to_var_int(iptr->dst, d);
714 case ICMD_LNEG: /* ..., value ==> ..., - value */
716 var_to_reg_int(s1, src, REG_ITMP1);
717 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
718 M_LSUB(REG_ZERO, s1, d);
719 store_reg_to_var_int(iptr->dst, d);
722 case ICMD_I2L: /* ..., value ==> ..., value */
724 var_to_reg_int(s1, src, REG_ITMP1);
725 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
727 store_reg_to_var_int(iptr->dst, d);
730 case ICMD_L2I: /* ..., value ==> ..., value */
732 var_to_reg_int(s1, src, REG_ITMP1);
733 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
734 M_ISLL_IMM(s1, 0, d );
735 store_reg_to_var_int(iptr->dst, d);
738 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
740 var_to_reg_int(s1, src, REG_ITMP1);
741 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
742 M_LSLL_IMM(s1, 56, d);
743 M_LSRA_IMM( d, 56, d);
744 store_reg_to_var_int(iptr->dst, d);
747 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
749 var_to_reg_int(s1, src, REG_ITMP1);
750 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
752 store_reg_to_var_int(iptr->dst, d);
755 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
757 var_to_reg_int(s1, src, REG_ITMP1);
758 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
759 M_LSLL_IMM(s1, 48, d);
760 M_LSRA_IMM( d, 48, d);
761 store_reg_to_var_int(iptr->dst, d);
765 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
767 var_to_reg_int(s1, src->prev, REG_ITMP1);
768 var_to_reg_int(s2, src, REG_ITMP2);
769 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
771 store_reg_to_var_int(iptr->dst, d);
774 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
775 /* val.i = constant */
777 var_to_reg_int(s1, src, REG_ITMP1);
778 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
779 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
780 M_IADD_IMM(s1, iptr->val.i, d);
782 ICONST(REG_ITMP2, iptr->val.i);
783 M_IADD(s1, REG_ITMP2, d);
785 store_reg_to_var_int(iptr->dst, d);
788 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
790 var_to_reg_int(s1, src->prev, REG_ITMP1);
791 var_to_reg_int(s2, src, REG_ITMP2);
792 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
794 store_reg_to_var_int(iptr->dst, d);
797 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
798 /* val.l = constant */
800 var_to_reg_int(s1, src, REG_ITMP1);
801 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
802 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
803 M_LADD_IMM(s1, iptr->val.l, d);
805 LCONST(REG_ITMP2, iptr->val.l);
806 M_LADD(s1, REG_ITMP2, d);
808 store_reg_to_var_int(iptr->dst, d);
811 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
813 var_to_reg_int(s1, src->prev, REG_ITMP1);
814 var_to_reg_int(s2, src, REG_ITMP2);
815 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
817 store_reg_to_var_int(iptr->dst, d);
820 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
821 /* val.i = constant */
823 var_to_reg_int(s1, src, REG_ITMP1);
824 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
825 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
826 M_IADD_IMM(s1, -iptr->val.i, d);
828 ICONST(REG_ITMP2, iptr->val.i);
829 M_ISUB(s1, REG_ITMP2, d);
831 store_reg_to_var_int(iptr->dst, d);
834 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
836 var_to_reg_int(s1, src->prev, REG_ITMP1);
837 var_to_reg_int(s2, src, REG_ITMP2);
838 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
840 store_reg_to_var_int(iptr->dst, d);
843 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
844 /* val.l = constant */
846 var_to_reg_int(s1, src, REG_ITMP1);
847 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
848 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
849 M_LADD_IMM(s1, -iptr->val.l, d);
851 LCONST(REG_ITMP2, iptr->val.l);
852 M_LSUB(s1, REG_ITMP2, d);
854 store_reg_to_var_int(iptr->dst, d);
857 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
859 var_to_reg_int(s1, src->prev, REG_ITMP1);
860 var_to_reg_int(s2, src, REG_ITMP2);
861 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
866 store_reg_to_var_int(iptr->dst, d);
869 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
870 /* val.i = constant */
872 var_to_reg_int(s1, src, REG_ITMP1);
873 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
874 ICONST(REG_ITMP2, iptr->val.i);
875 M_IMUL(s1, REG_ITMP2);
879 store_reg_to_var_int(iptr->dst, d);
882 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
884 var_to_reg_int(s1, src->prev, REG_ITMP1);
885 var_to_reg_int(s2, src, REG_ITMP2);
886 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
891 store_reg_to_var_int(iptr->dst, d);
894 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
895 /* val.l = constant */
897 var_to_reg_int(s1, src, REG_ITMP1);
898 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
899 LCONST(REG_ITMP2, iptr->val.l);
900 M_LMUL(s1, REG_ITMP2);
904 store_reg_to_var_int(iptr->dst, d);
907 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
909 var_to_reg_int(s1, src->prev, REG_ITMP1);
910 var_to_reg_int(s2, src, REG_ITMP2);
911 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
917 store_reg_to_var_int(iptr->dst, d);
920 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
922 var_to_reg_int(s1, src->prev, REG_ITMP1);
923 var_to_reg_int(s2, src, REG_ITMP2);
924 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
930 store_reg_to_var_int(iptr->dst, d);
933 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
935 var_to_reg_int(s1, src->prev, REG_ITMP1);
936 var_to_reg_int(s2, src, REG_ITMP2);
937 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
943 store_reg_to_var_int(iptr->dst, d);
946 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
948 var_to_reg_int(s1, src->prev, REG_ITMP1);
949 var_to_reg_int(s2, src, REG_ITMP2);
950 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
956 store_reg_to_var_int(iptr->dst, d);
959 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
960 case ICMD_LDIVPOW2: /* val.i = constant */
962 var_to_reg_int(s1, src, REG_ITMP1);
963 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
964 M_LSRA_IMM(s1, 63, REG_ITMP2);
965 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
966 M_LADD(s1, REG_ITMP2, REG_ITMP2);
967 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
968 store_reg_to_var_int(iptr->dst, d);
971 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
973 var_to_reg_int(s1, src->prev, REG_ITMP1);
974 var_to_reg_int(s2, src, REG_ITMP2);
975 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
977 store_reg_to_var_int(iptr->dst, d);
980 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
981 /* val.i = constant */
983 var_to_reg_int(s1, src, REG_ITMP1);
984 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
985 M_ISLL_IMM(s1, iptr->val.i, d);
986 store_reg_to_var_int(iptr->dst, d);
989 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
991 var_to_reg_int(s1, src->prev, REG_ITMP1);
992 var_to_reg_int(s2, src, REG_ITMP2);
993 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
995 store_reg_to_var_int(iptr->dst, d);
998 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
999 /* val.i = constant */
1001 var_to_reg_int(s1, src, REG_ITMP1);
1002 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1003 M_ISRA_IMM(s1, iptr->val.i, d);
1004 store_reg_to_var_int(iptr->dst, d);
1007 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1009 var_to_reg_int(s1, src->prev, REG_ITMP1);
1010 var_to_reg_int(s2, src, REG_ITMP2);
1011 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1013 store_reg_to_var_int(iptr->dst, d);
1016 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1017 /* val.i = constant */
1019 var_to_reg_int(s1, src, REG_ITMP1);
1020 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1021 M_ISRL_IMM(s1, iptr->val.i, d);
1022 store_reg_to_var_int(iptr->dst, d);
1025 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1027 var_to_reg_int(s1, src->prev, REG_ITMP1);
1028 var_to_reg_int(s2, src, REG_ITMP2);
1029 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1031 store_reg_to_var_int(iptr->dst, d);
1034 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1035 /* val.i = constant */
1037 var_to_reg_int(s1, src, REG_ITMP1);
1038 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1039 M_LSLL_IMM(s1, iptr->val.i, d);
1040 store_reg_to_var_int(iptr->dst, d);
1043 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1045 var_to_reg_int(s1, src->prev, REG_ITMP1);
1046 var_to_reg_int(s2, src, REG_ITMP2);
1047 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1049 store_reg_to_var_int(iptr->dst, d);
1052 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1053 /* val.i = constant */
1055 var_to_reg_int(s1, src, REG_ITMP1);
1056 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1057 M_LSRA_IMM(s1, iptr->val.i, d);
1058 store_reg_to_var_int(iptr->dst, d);
1061 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1063 var_to_reg_int(s1, src->prev, REG_ITMP1);
1064 var_to_reg_int(s2, src, REG_ITMP2);
1065 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1067 store_reg_to_var_int(iptr->dst, d);
1070 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1071 /* val.i = constant */
1073 var_to_reg_int(s1, src, REG_ITMP1);
1074 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1075 M_LSRL_IMM(s1, iptr->val.i, d);
1076 store_reg_to_var_int(iptr->dst, d);
1079 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1082 var_to_reg_int(s1, src->prev, REG_ITMP1);
1083 var_to_reg_int(s2, src, REG_ITMP2);
1084 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1086 store_reg_to_var_int(iptr->dst, d);
1089 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1090 /* val.i = constant */
1092 var_to_reg_int(s1, src, REG_ITMP1);
1093 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1094 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1095 M_AND_IMM(s1, iptr->val.i, d);
1097 ICONST(REG_ITMP2, iptr->val.i);
1098 M_AND(s1, REG_ITMP2, d);
1100 store_reg_to_var_int(iptr->dst, d);
1103 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1104 /* val.i = constant */
1106 var_to_reg_int(s1, src, REG_ITMP1);
1107 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1109 M_MOV(s1, REG_ITMP1);
1112 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1113 M_AND_IMM(s1, iptr->val.i, d);
1116 M_ISUB(REG_ZERO, s1, d);
1117 M_AND_IMM(d, iptr->val.i, d);
1119 ICONST(REG_ITMP2, iptr->val.i);
1120 M_AND(s1, REG_ITMP2, d);
1123 M_ISUB(REG_ZERO, s1, d);
1124 M_AND(d, REG_ITMP2, d);
1126 M_ISUB(REG_ZERO, d, d);
1127 store_reg_to_var_int(iptr->dst, d);
1130 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1131 /* val.l = constant */
1133 var_to_reg_int(s1, src, REG_ITMP1);
1134 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1135 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1136 M_AND_IMM(s1, iptr->val.l, d);
1138 LCONST(REG_ITMP2, iptr->val.l);
1139 M_AND(s1, REG_ITMP2, d);
1141 store_reg_to_var_int(iptr->dst, d);
1144 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1145 /* val.l = constant */
1147 var_to_reg_int(s1, src, REG_ITMP1);
1148 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1150 M_MOV(s1, REG_ITMP1);
1153 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1154 M_AND_IMM(s1, iptr->val.l, d);
1157 M_LSUB(REG_ZERO, s1, d);
1158 M_AND_IMM(d, iptr->val.l, d);
1160 LCONST(REG_ITMP2, iptr->val.l);
1161 M_AND(s1, REG_ITMP2, d);
1164 M_LSUB(REG_ZERO, s1, d);
1165 M_AND(d, REG_ITMP2, d);
1167 M_LSUB(REG_ZERO, d, d);
1168 store_reg_to_var_int(iptr->dst, d);
1171 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1174 var_to_reg_int(s1, src->prev, REG_ITMP1);
1175 var_to_reg_int(s2, src, REG_ITMP2);
1176 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1178 store_reg_to_var_int(iptr->dst, d);
1181 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1182 /* val.i = constant */
1184 var_to_reg_int(s1, src, REG_ITMP1);
1185 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1186 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1187 M_OR_IMM(s1, iptr->val.i, d);
1189 ICONST(REG_ITMP2, iptr->val.i);
1190 M_OR(s1, REG_ITMP2, d);
1192 store_reg_to_var_int(iptr->dst, d);
1195 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1196 /* val.l = constant */
1198 var_to_reg_int(s1, src, REG_ITMP1);
1199 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1200 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1201 M_OR_IMM(s1, iptr->val.l, d);
1203 LCONST(REG_ITMP2, iptr->val.l);
1204 M_OR(s1, REG_ITMP2, d);
1206 store_reg_to_var_int(iptr->dst, d);
1209 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1212 var_to_reg_int(s1, src->prev, REG_ITMP1);
1213 var_to_reg_int(s2, src, REG_ITMP2);
1214 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1216 store_reg_to_var_int(iptr->dst, d);
1219 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1220 /* val.i = constant */
1222 var_to_reg_int(s1, src, REG_ITMP1);
1223 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1224 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1225 M_XOR_IMM(s1, iptr->val.i, d);
1227 ICONST(REG_ITMP2, iptr->val.i);
1228 M_XOR(s1, REG_ITMP2, d);
1230 store_reg_to_var_int(iptr->dst, d);
1233 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1234 /* val.l = constant */
1236 var_to_reg_int(s1, src, REG_ITMP1);
1237 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1238 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1239 M_XOR_IMM(s1, iptr->val.l, d);
1241 LCONST(REG_ITMP2, iptr->val.l);
1242 M_XOR(s1, REG_ITMP2, d);
1244 store_reg_to_var_int(iptr->dst, d);
1248 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1250 var_to_reg_int(s1, src->prev, REG_ITMP1);
1251 var_to_reg_int(s2, src, REG_ITMP2);
1252 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1253 M_CMPLT(s1, s2, REG_ITMP3);
1254 M_CMPLT(s2, s1, REG_ITMP1);
1255 M_LSUB(REG_ITMP1, REG_ITMP3, d);
1256 store_reg_to_var_int(iptr->dst, d);
1260 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1261 /* op1 = variable, val.i = constant */
1263 var = &(rd->locals[iptr->op1][TYPE_INT]);
1264 if (var->flags & INMEMORY) {
1266 M_LLD(s1, REG_SP, var->regoff * 8);
1269 M_IADD_IMM(s1, iptr->val.i, s1);
1270 if (var->flags & INMEMORY)
1271 M_LST(s1, REG_SP, var->regoff * 8);
1275 /* floating operations ************************************************/
1277 case ICMD_FNEG: /* ..., value ==> ..., - value */
1279 var_to_reg_flt(s1, src, REG_FTMP1);
1280 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1282 store_reg_to_var_flt(iptr->dst, d);
1285 case ICMD_DNEG: /* ..., value ==> ..., - value */
1287 var_to_reg_flt(s1, src, REG_FTMP1);
1288 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1290 store_reg_to_var_flt(iptr->dst, d);
1293 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1295 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1296 var_to_reg_flt(s2, src, REG_FTMP2);
1297 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1299 store_reg_to_var_flt(iptr->dst, d);
1302 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1304 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1305 var_to_reg_flt(s2, src, REG_FTMP2);
1306 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1308 store_reg_to_var_flt(iptr->dst, d);
1311 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1313 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1314 var_to_reg_flt(s2, src, REG_FTMP2);
1315 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1317 store_reg_to_var_flt(iptr->dst, d);
1320 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1322 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1323 var_to_reg_flt(s2, src, REG_FTMP2);
1324 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1326 store_reg_to_var_flt(iptr->dst, d);
1329 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1331 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1332 var_to_reg_flt(s2, src, REG_FTMP2);
1333 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1335 store_reg_to_var_flt(iptr->dst, d);
1338 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1340 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1341 var_to_reg_flt(s2, src, REG_FTMP2);
1342 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1344 store_reg_to_var_flt(iptr->dst, d);
1347 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1349 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1350 var_to_reg_flt(s2, src, REG_FTMP2);
1351 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1353 store_reg_to_var_flt(iptr->dst, d);
1356 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1358 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1359 var_to_reg_flt(s2, src, REG_FTMP2);
1360 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1362 store_reg_to_var_flt(iptr->dst, d);
1366 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1368 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1369 var_to_reg_flt(s2, src, REG_FTMP2);
1370 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1371 M_FDIV(s1,s2, REG_FTMP3);
1372 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1373 M_CVTLF(REG_FTMP3, REG_FTMP3);
1374 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1375 M_FSUB(s1, REG_FTMP3, d);
1376 store_reg_to_var_flt(iptr->dst, d);
1379 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1381 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1382 var_to_reg_flt(s2, src, REG_FTMP2);
1383 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1384 M_DDIV(s1,s2, REG_FTMP3);
1385 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1386 M_CVTLD(REG_FTMP3, REG_FTMP3);
1387 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1388 M_DSUB(s1, REG_FTMP3, d);
1389 store_reg_to_var_flt(iptr->dst, d);
1393 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1395 var_to_reg_int(s1, src, REG_ITMP1);
1396 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1399 store_reg_to_var_flt(iptr->dst, d);
1402 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1404 var_to_reg_int(s1, src, REG_ITMP1);
1405 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1408 store_reg_to_var_flt(iptr->dst, d);
1412 /* XXX these do not work correctly */
1414 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1416 var_to_reg_flt(s1, src, REG_FTMP1);
1417 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1418 M_TRUNCFI(s1, REG_FTMP1);
1419 M_MOVDI(REG_FTMP1, d);
1421 store_reg_to_var_int(iptr->dst, d);
1424 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1426 var_to_reg_flt(s1, src, REG_FTMP1);
1427 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1428 M_TRUNCDI(s1, REG_FTMP1);
1429 M_MOVDI(REG_FTMP1, d);
1431 store_reg_to_var_int(iptr->dst, d);
1434 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1436 var_to_reg_flt(s1, src, REG_FTMP1);
1437 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1438 M_TRUNCFL(s1, REG_FTMP1);
1439 M_MOVDL(REG_FTMP1, d);
1441 store_reg_to_var_int(iptr->dst, d);
1444 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1446 var_to_reg_flt(s1, src, REG_FTMP1);
1447 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1448 M_TRUNCDL(s1, REG_FTMP1);
1449 M_MOVDL(REG_FTMP1, d);
1451 store_reg_to_var_int(iptr->dst, d);
1455 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1457 var_to_reg_flt(s1, src, REG_FTMP1);
1458 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1460 store_reg_to_var_flt(iptr->dst, d);
1463 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1465 var_to_reg_flt(s1, src, REG_FTMP1);
1466 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1468 store_reg_to_var_flt(iptr->dst, d);
1471 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1473 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1474 var_to_reg_flt(s2, src, REG_FTMP2);
1475 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1478 M_LADD_IMM(REG_ZERO, 1, d);
1482 M_LSUB_IMM(REG_ZERO, 1, d);
1483 M_CMOVT(REG_ZERO, d);
1484 store_reg_to_var_int(iptr->dst, d);
1487 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1489 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1490 var_to_reg_flt(s2, src, REG_FTMP2);
1491 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1494 M_LADD_IMM(REG_ZERO, 1, d);
1498 M_LSUB_IMM(REG_ZERO, 1, d);
1499 M_CMOVT(REG_ZERO, d);
1500 store_reg_to_var_int(iptr->dst, d);
1503 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1505 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1506 var_to_reg_flt(s2, src, REG_FTMP2);
1507 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1510 M_LSUB_IMM(REG_ZERO, 1, d);
1514 M_LADD_IMM(REG_ZERO, 1, d);
1515 M_CMOVT(REG_ZERO, d);
1516 store_reg_to_var_int(iptr->dst, d);
1519 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1521 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1522 var_to_reg_flt(s2, src, REG_FTMP2);
1523 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1526 M_LSUB_IMM(REG_ZERO, 1, d);
1530 M_LADD_IMM(REG_ZERO, 1, d);
1531 M_CMOVT(REG_ZERO, d);
1532 store_reg_to_var_int(iptr->dst, d);
1536 /* memory operations **************************************************/
1538 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1540 var_to_reg_int(s1, src, REG_ITMP1);
1541 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1542 gen_nullptr_check(s1);
1543 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1544 store_reg_to_var_int(iptr->dst, d);
1547 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1549 var_to_reg_int(s1, src->prev, REG_ITMP1);
1550 var_to_reg_int(s2, src, REG_ITMP2);
1551 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1552 if (iptr->op1 == 0) {
1553 gen_nullptr_check(s1);
1556 M_AADD(s2, s1, REG_ITMP3);
1557 M_BLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1558 store_reg_to_var_int(iptr->dst, d);
1561 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1563 var_to_reg_int(s1, src->prev, REG_ITMP1);
1564 var_to_reg_int(s2, src, REG_ITMP2);
1565 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1566 if (iptr->op1 == 0) {
1567 gen_nullptr_check(s1);
1570 M_AADD(s2, s1, REG_ITMP3);
1571 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1572 M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1573 store_reg_to_var_int(iptr->dst, d);
1576 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1578 var_to_reg_int(s1, src->prev, REG_ITMP1);
1579 var_to_reg_int(s2, src, REG_ITMP2);
1580 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1581 if (iptr->op1 == 0) {
1582 gen_nullptr_check(s1);
1585 M_AADD(s2, s1, REG_ITMP3);
1586 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1587 M_SLDS(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1588 store_reg_to_var_int(iptr->dst, d);
1591 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1593 var_to_reg_int(s1, src->prev, REG_ITMP1);
1594 var_to_reg_int(s2, src, REG_ITMP2);
1595 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1596 if (iptr->op1 == 0) {
1597 gen_nullptr_check(s1);
1600 M_ASLL_IMM(s2, 2, REG_ITMP3);
1601 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1602 M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
1603 store_reg_to_var_int(iptr->dst, d);
1606 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1608 var_to_reg_int(s1, src->prev, REG_ITMP1);
1609 var_to_reg_int(s2, src, REG_ITMP2);
1610 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1611 if (iptr->op1 == 0) {
1612 gen_nullptr_check(s1);
1615 M_ASLL_IMM(s2, 3, REG_ITMP3);
1616 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1617 M_LLD(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
1618 store_reg_to_var_int(iptr->dst, d);
1621 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1623 var_to_reg_int(s1, src->prev, REG_ITMP1);
1624 var_to_reg_int(s2, src, REG_ITMP2);
1625 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1626 if (iptr->op1 == 0) {
1627 gen_nullptr_check(s1);
1630 M_ASLL_IMM(s2, 2, REG_ITMP3);
1631 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1632 M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
1633 store_reg_to_var_flt(iptr->dst, d);
1636 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1638 var_to_reg_int(s1, src->prev, REG_ITMP1);
1639 var_to_reg_int(s2, src, REG_ITMP2);
1640 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1641 if (iptr->op1 == 0) {
1642 gen_nullptr_check(s1);
1645 M_ASLL_IMM(s2, 3, REG_ITMP3);
1646 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1647 M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
1648 store_reg_to_var_flt(iptr->dst, d);
1651 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1653 var_to_reg_int(s1, src->prev, REG_ITMP1);
1654 var_to_reg_int(s2, src, REG_ITMP2);
1655 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1656 if (iptr->op1 == 0) {
1657 gen_nullptr_check(s1);
1660 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1661 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1662 M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
1663 store_reg_to_var_int(iptr->dst, d);
1667 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1669 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1670 var_to_reg_int(s2, src->prev, REG_ITMP2);
1671 if (iptr->op1 == 0) {
1672 gen_nullptr_check(s1);
1675 M_AADD(s2, s1, REG_ITMP1);
1676 var_to_reg_int(s3, src, REG_ITMP3);
1677 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1680 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1681 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1683 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1684 var_to_reg_int(s2, src->prev, REG_ITMP2);
1685 if (iptr->op1 == 0) {
1686 gen_nullptr_check(s1);
1689 M_AADD(s2, s1, REG_ITMP1);
1690 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1691 var_to_reg_int(s3, src, REG_ITMP3);
1692 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1695 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1697 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1698 var_to_reg_int(s2, src->prev, REG_ITMP2);
1699 if (iptr->op1 == 0) {
1700 gen_nullptr_check(s1);
1703 M_ASLL_IMM(s2, 2, REG_ITMP2);
1704 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1705 var_to_reg_int(s3, src, REG_ITMP3);
1706 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1709 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1711 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1712 var_to_reg_int(s2, src->prev, REG_ITMP2);
1713 if (iptr->op1 == 0) {
1714 gen_nullptr_check(s1);
1717 M_ASLL_IMM(s2, 3, REG_ITMP2);
1718 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1719 var_to_reg_int(s3, src, REG_ITMP3);
1720 M_LST_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1723 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1725 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1726 var_to_reg_int(s2, src->prev, REG_ITMP2);
1727 if (iptr->op1 == 0) {
1728 gen_nullptr_check(s1);
1731 M_ASLL_IMM(s2, 2, REG_ITMP2);
1732 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1733 var_to_reg_flt(s3, src, REG_FTMP1);
1734 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1737 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1739 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1740 var_to_reg_int(s2, src->prev, REG_ITMP2);
1741 if (iptr->op1 == 0) {
1742 gen_nullptr_check(s1);
1745 M_ASLL_IMM(s2, 3, REG_ITMP2);
1746 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1747 var_to_reg_flt(s3, src, REG_FTMP1);
1748 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1752 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1754 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1755 var_to_reg_int(s2, src->prev, REG_ITMP2);
1756 if (iptr->op1 == 0) {
1757 gen_nullptr_check(s1);
1760 var_to_reg_int(s3, src, REG_ITMP3);
1762 M_MOV(s1, rd->argintregs[0]);
1763 M_MOV(s3, rd->argintregs[1]);
1764 disp = dseg_addaddress(cd, BUILTIN_canstore);
1765 M_ALD(REG_ITMP3, REG_PV, disp);
1766 M_JSR(REG_RA, REG_ITMP3);
1769 M_BEQZ(REG_RESULT, 0);
1770 codegen_add_arraystoreexception_ref(cd, mcodeptr);
1773 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1774 var_to_reg_int(s2, src->prev, REG_ITMP2);
1775 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1776 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1777 var_to_reg_int(s3, src, REG_ITMP3);
1778 M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1782 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1784 var_to_reg_int(s1, src->prev, REG_ITMP1);
1785 var_to_reg_int(s2, src, REG_ITMP2);
1786 if (iptr->op1 == 0) {
1787 gen_nullptr_check(s1);
1790 M_AADD(s2, s1, REG_ITMP1);
1791 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1794 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1795 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1797 var_to_reg_int(s1, src->prev, REG_ITMP1);
1798 var_to_reg_int(s2, src, REG_ITMP2);
1799 if (iptr->op1 == 0) {
1800 gen_nullptr_check(s1);
1803 M_AADD(s2, s1, REG_ITMP1);
1804 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1805 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
1808 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1810 var_to_reg_int(s1, src->prev, REG_ITMP1);
1811 var_to_reg_int(s2, src, REG_ITMP2);
1812 if (iptr->op1 == 0) {
1813 gen_nullptr_check(s1);
1816 M_ASLL_IMM(s2, 2, REG_ITMP2);
1817 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1818 M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1821 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1823 var_to_reg_int(s1, src->prev, REG_ITMP1);
1824 var_to_reg_int(s2, src, REG_ITMP2);
1825 if (iptr->op1 == 0) {
1826 gen_nullptr_check(s1);
1829 M_ASLL_IMM(s2, 3, REG_ITMP2);
1830 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1831 M_LST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1834 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1836 var_to_reg_int(s1, src->prev, REG_ITMP1);
1837 var_to_reg_int(s2, src, REG_ITMP2);
1838 if (iptr->op1 == 0) {
1839 gen_nullptr_check(s1);
1842 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1843 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1844 M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1848 case ICMD_GETSTATIC: /* ... ==> ..., value */
1849 /* op1 = type, val.a = field address */
1851 if (iptr->val.a == NULL) {
1852 disp = dseg_addaddress(cd, NULL);
1854 codegen_addpatchref(cd, mcodeptr,
1855 PATCHER_get_putstatic,
1856 (unresolved_field *) iptr->target, disp);
1858 if (opt_showdisassemble) {
1863 fieldinfo *fi = iptr->val.a;
1865 disp = dseg_addaddress(cd, &(fi->value));
1867 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1868 codegen_addpatchref(cd, mcodeptr,
1869 PATCHER_clinit, fi->class, 0);
1871 if (opt_showdisassemble) {
1877 M_ALD(REG_ITMP1, REG_PV, disp);
1878 switch (iptr->op1) {
1880 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1881 M_ILD_INTERN(d, REG_ITMP1, 0);
1882 store_reg_to_var_int(iptr->dst, d);
1885 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1886 M_LLD_INTERN(d, REG_ITMP1, 0);
1887 store_reg_to_var_int(iptr->dst, d);
1890 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1891 M_ALD_INTERN(d, REG_ITMP1, 0);
1892 store_reg_to_var_int(iptr->dst, d);
1895 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1896 M_FLD_INTERN(d, REG_ITMP1, 0);
1897 store_reg_to_var_flt(iptr->dst, d);
1900 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1901 M_DLD_INTERN(d, REG_ITMP1, 0);
1902 store_reg_to_var_flt(iptr->dst, d);
1907 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1908 /* op1 = type, val.a = field address */
1910 if (iptr->val.a == NULL) {
1911 disp = dseg_addaddress(cd, NULL);
1913 codegen_addpatchref(cd, mcodeptr,
1914 PATCHER_get_putstatic,
1915 (unresolved_field *) iptr->target, disp);
1917 if (opt_showdisassemble) {
1922 fieldinfo *fi = iptr->val.a;
1924 disp = dseg_addaddress(cd, &(fi->value));
1926 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1927 codegen_addpatchref(cd, mcodeptr,
1928 PATCHER_clinit, fi->class, 0);
1930 if (opt_showdisassemble) {
1936 M_ALD(REG_ITMP1, REG_PV, disp);
1937 switch (iptr->op1) {
1939 var_to_reg_int(s2, src, REG_ITMP2);
1940 M_IST_INTERN(s2, REG_ITMP1, 0);
1943 var_to_reg_int(s2, src, REG_ITMP2);
1944 M_LST_INTERN(s2, REG_ITMP1, 0);
1947 var_to_reg_int(s2, src, REG_ITMP2);
1948 M_AST_INTERN(s2, REG_ITMP1, 0);
1951 var_to_reg_flt(s2, src, REG_FTMP2);
1952 M_FST_INTERN(s2, REG_ITMP1, 0);
1955 var_to_reg_flt(s2, src, REG_FTMP2);
1956 M_DST_INTERN(s2, REG_ITMP1, 0);
1961 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1962 /* val = value (in current instruction) */
1963 /* op1 = type, val.a = field address (in */
1964 /* following NOP) */
1966 if (iptr[1].val.a == NULL) {
1967 disp = dseg_addaddress(cd, NULL);
1969 codegen_addpatchref(cd, mcodeptr,
1970 PATCHER_get_putstatic,
1971 (unresolved_field *) iptr[1].target, disp);
1973 if (opt_showdisassemble) {
1978 fieldinfo *fi = iptr[1].val.a;
1980 disp = dseg_addaddress(cd, &(fi->value));
1982 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1983 codegen_addpatchref(cd, mcodeptr,
1984 PATCHER_clinit, fi->class, 0);
1986 if (opt_showdisassemble) {
1992 M_ALD(REG_ITMP1, REG_PV, disp);
1993 switch (iptr->op1) {
1995 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1998 M_LST_INTERN(REG_ZERO, REG_ITMP1, 0);
2001 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
2004 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
2007 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
2013 case ICMD_GETFIELD: /* ... ==> ..., value */
2014 /* op1 = type, val.i = field offset */
2016 var_to_reg_int(s1, src, REG_ITMP1);
2017 gen_nullptr_check(s1);
2019 if (iptr->val.a == NULL) {
2020 codegen_addpatchref(cd, mcodeptr,
2021 PATCHER_get_putfield,
2022 (unresolved_field *) iptr->target, 0);
2024 if (opt_showdisassemble) {
2031 a = ((fieldinfo *) (iptr->val.a))->offset;
2034 switch (iptr->op1) {
2036 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2038 store_reg_to_var_int(iptr->dst, d);
2041 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2043 store_reg_to_var_int(iptr->dst, d);
2046 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2048 store_reg_to_var_int(iptr->dst, d);
2051 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2053 store_reg_to_var_flt(iptr->dst, d);
2056 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2058 store_reg_to_var_flt(iptr->dst, d);
2063 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2064 /* op1 = type, val.a = field address */
2066 var_to_reg_int(s1, src->prev, REG_ITMP1);
2067 gen_nullptr_check(s1);
2069 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2070 var_to_reg_int(s2, src, REG_ITMP2);
2072 var_to_reg_flt(s2, src, REG_FTMP2);
2075 if (iptr->val.a == NULL) {
2076 codegen_addpatchref(cd, mcodeptr,
2077 PATCHER_get_putfield,
2078 (unresolved_field *) iptr->target, 0);
2080 if (opt_showdisassemble) {
2087 a = ((fieldinfo *) (iptr->val.a))->offset;
2090 switch (iptr->op1) {
2109 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2110 /* val = value (in current instruction) */
2111 /* op1 = type, val.a = field address (in */
2112 /* following NOP) */
2114 var_to_reg_int(s1, src, REG_ITMP1);
2115 gen_nullptr_check(s1);
2117 if (iptr[1].val.a == NULL) {
2118 codegen_addpatchref(cd, mcodeptr,
2119 PATCHER_get_putfield,
2120 (unresolved_field *) iptr[1].target, 0);
2122 if (opt_showdisassemble) {
2129 a = ((fieldinfo *) (iptr[1].val.a))->offset;
2132 switch (iptr[1].op1) {
2134 M_IST(REG_ZERO, s1, a);
2137 M_LST(REG_ZERO, s1, a);
2140 M_AST(REG_ZERO, s1, a);
2143 M_FST(REG_ZERO, s1, a);
2146 M_DST(REG_ZERO, s1, a);
2152 /* branch operations **************************************************/
2154 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2156 var_to_reg_int(s1, src, REG_ITMP1);
2157 M_INTMOVE(s1, REG_ITMP1_XPTR);
2159 #ifdef ENABLE_VERIFIER
2161 codegen_addpatchref(cd, mcodeptr,
2162 PATCHER_athrow_areturn,
2163 (unresolved_class *) iptr->val.a, 0);
2165 if (opt_showdisassemble) {
2169 #endif /* ENABLE_VERIFIER */
2171 disp = dseg_addaddress(cd, asm_handle_exception);
2172 M_ALD(REG_ITMP2, REG_PV, disp);
2173 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2175 M_NOP; /* nop ensures that XPC is less than the end */
2176 /* of basic block */
2180 case ICMD_GOTO: /* ... ==> ... */
2181 /* op1 = target JavaVM pc */
2183 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2188 case ICMD_JSR: /* ... ==> ... */
2189 /* op1 = target JavaVM pc */
2191 dseg_addtarget(cd, (basicblock *) iptr->target);
2192 M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
2193 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2197 case ICMD_RET: /* ... ==> ... */
2198 /* op1 = local variable */
2199 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2200 if (var->flags & INMEMORY) {
2201 M_ALD(REG_ITMP1, REG_SP, var->regoff * 8);
2209 case ICMD_IFNULL: /* ..., value ==> ... */
2210 /* op1 = target JavaVM pc */
2212 var_to_reg_int(s1, src, REG_ITMP1);
2214 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2218 case ICMD_IFNONNULL: /* ..., value ==> ... */
2219 /* op1 = target JavaVM pc */
2221 var_to_reg_int(s1, src, REG_ITMP1);
2223 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2227 case ICMD_IFEQ: /* ..., value ==> ... */
2228 /* op1 = target JavaVM pc, val.i = constant */
2230 var_to_reg_int(s1, src, REG_ITMP1);
2231 if (iptr->val.i == 0) {
2234 ICONST(REG_ITMP2, iptr->val.i);
2235 M_BEQ(s1, REG_ITMP2, 0);
2237 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2241 case ICMD_IFLT: /* ..., value ==> ... */
2242 /* op1 = target JavaVM pc, val.i = constant */
2244 var_to_reg_int(s1, src, REG_ITMP1);
2245 if (iptr->val.i == 0) {
2248 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2249 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2251 ICONST(REG_ITMP2, iptr->val.i);
2252 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2254 M_BNEZ(REG_ITMP1, 0);
2256 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2260 case ICMD_IFLE: /* ..., value ==> ... */
2261 /* op1 = target JavaVM pc, val.i = constant */
2263 var_to_reg_int(s1, src, REG_ITMP1);
2264 if (iptr->val.i == 0) {
2268 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2269 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2270 M_BNEZ(REG_ITMP1, 0);
2273 ICONST(REG_ITMP2, iptr->val.i);
2274 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2275 M_BEQZ(REG_ITMP1, 0);
2278 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2282 case ICMD_IFNE: /* ..., value ==> ... */
2283 /* op1 = target JavaVM pc, val.i = constant */
2285 var_to_reg_int(s1, src, REG_ITMP1);
2286 if (iptr->val.i == 0) {
2290 ICONST(REG_ITMP2, iptr->val.i);
2291 M_BNE(s1, REG_ITMP2, 0);
2293 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2297 case ICMD_IFGT: /* ..., value ==> ... */
2298 /* op1 = target JavaVM pc, val.i = constant */
2300 var_to_reg_int(s1, src, REG_ITMP1);
2301 if (iptr->val.i == 0) {
2305 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2306 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2307 M_BEQZ(REG_ITMP1, 0);
2310 ICONST(REG_ITMP2, iptr->val.i);
2311 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2312 M_BNEZ(REG_ITMP1, 0);
2315 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2319 case ICMD_IFGE: /* ..., value ==> ... */
2320 /* op1 = target JavaVM pc, val.i = constant */
2322 var_to_reg_int(s1, src, REG_ITMP1);
2323 if (iptr->val.i == 0) {
2327 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2328 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2331 ICONST(REG_ITMP2, iptr->val.i);
2332 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2334 M_BEQZ(REG_ITMP1, 0);
2336 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2340 case ICMD_IF_LEQ: /* ..., value ==> ... */
2341 /* op1 = target JavaVM pc, val.l = constant */
2343 var_to_reg_int(s1, src, REG_ITMP1);
2344 if (iptr->val.l == 0) {
2348 LCONST(REG_ITMP2, iptr->val.l);
2349 M_BEQ(s1, REG_ITMP2, 0);
2351 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2355 case ICMD_IF_LLT: /* ..., value ==> ... */
2356 /* op1 = target JavaVM pc, val.l = constant */
2358 var_to_reg_int(s1, src, REG_ITMP1);
2359 if (iptr->val.l == 0) {
2363 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2364 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2367 LCONST(REG_ITMP2, iptr->val.l);
2368 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2370 M_BNEZ(REG_ITMP1, 0);
2372 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2376 case ICMD_IF_LLE: /* ..., value ==> ... */
2377 /* op1 = target JavaVM pc, val.l = constant */
2379 var_to_reg_int(s1, src, REG_ITMP1);
2380 if (iptr->val.l == 0) {
2384 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2385 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2386 M_BNEZ(REG_ITMP1, 0);
2389 LCONST(REG_ITMP2, iptr->val.l);
2390 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2391 M_BEQZ(REG_ITMP1, 0);
2394 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2398 case ICMD_IF_LNE: /* ..., value ==> ... */
2399 /* op1 = target JavaVM pc, val.l = constant */
2401 var_to_reg_int(s1, src, REG_ITMP1);
2402 if (iptr->val.l == 0) {
2406 LCONST(REG_ITMP2, iptr->val.l);
2407 M_BNE(s1, REG_ITMP2, 0);
2409 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2413 case ICMD_IF_LGT: /* ..., value ==> ... */
2414 /* op1 = target JavaVM pc, val.l = constant */
2416 var_to_reg_int(s1, src, REG_ITMP1);
2417 if (iptr->val.l == 0) {
2421 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2422 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2423 M_BEQZ(REG_ITMP1, 0);
2426 LCONST(REG_ITMP2, iptr->val.l);
2427 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2428 M_BNEZ(REG_ITMP1, 0);
2431 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2435 case ICMD_IF_LGE: /* ..., value ==> ... */
2436 /* op1 = target JavaVM pc, val.l = constant */
2438 var_to_reg_int(s1, src, REG_ITMP1);
2439 if (iptr->val.l == 0) {
2443 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2444 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2447 LCONST(REG_ITMP2, iptr->val.l);
2448 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2450 M_BEQZ(REG_ITMP1, 0);
2452 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2456 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2457 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2458 case ICMD_IF_ACMPEQ:
2460 var_to_reg_int(s1, src->prev, REG_ITMP1);
2461 var_to_reg_int(s2, src, REG_ITMP2);
2463 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2467 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2468 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2469 case ICMD_IF_ACMPNE:
2471 var_to_reg_int(s1, src->prev, REG_ITMP1);
2472 var_to_reg_int(s2, src, REG_ITMP2);
2474 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2478 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2479 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2481 var_to_reg_int(s1, src->prev, REG_ITMP1);
2482 var_to_reg_int(s2, src, REG_ITMP2);
2483 M_CMPLT(s1, s2, REG_ITMP1);
2484 M_BNEZ(REG_ITMP1, 0);
2485 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2489 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2490 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2492 var_to_reg_int(s1, src->prev, REG_ITMP1);
2493 var_to_reg_int(s2, src, REG_ITMP2);
2494 M_CMPGT(s1, s2, REG_ITMP1);
2495 M_BNEZ(REG_ITMP1, 0);
2496 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2500 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2501 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2503 var_to_reg_int(s1, src->prev, REG_ITMP1);
2504 var_to_reg_int(s2, src, REG_ITMP2);
2505 M_CMPGT(s1, s2, REG_ITMP1);
2506 M_BEQZ(REG_ITMP1, 0);
2507 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2511 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2512 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2514 var_to_reg_int(s1, src->prev, REG_ITMP1);
2515 var_to_reg_int(s2, src, REG_ITMP2);
2516 M_CMPLT(s1, s2, REG_ITMP1);
2517 M_BEQZ(REG_ITMP1, 0);
2518 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2522 #ifdef CONDITIONAL_LOADCONST
2523 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2525 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2528 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2529 /* val.i = constant */
2531 var_to_reg_int(s1, src, REG_ITMP1);
2532 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2534 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2535 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2536 M_CMPEQ(s1, REG_ZERO, d);
2537 store_reg_to_var_int(iptr->dst, d);
2540 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2541 M_CMPEQ(s1, REG_ZERO, d);
2543 store_reg_to_var_int(iptr->dst, d);
2547 M_MOV(s1, REG_ITMP1);
2550 ICONST(d, iptr[1].val.i);
2552 if ((s3 >= 0) && (s3 <= 255)) {
2553 M_CMOVEQ_IMM(s1, s3, d);
2555 ICONST(REG_ITMP3, s3);
2556 M_CMOVEQ(s1, REG_ITMP3, d);
2558 store_reg_to_var_int(iptr->dst, d);
2561 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2562 /* val.i = constant */
2564 var_to_reg_int(s1, src, REG_ITMP1);
2565 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2567 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2568 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2569 M_CMPEQ(s1, REG_ZERO, d);
2570 store_reg_to_var_int(iptr->dst, d);
2573 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2574 M_CMPEQ(s1, REG_ZERO, d);
2576 store_reg_to_var_int(iptr->dst, d);
2580 M_MOV(s1, REG_ITMP1);
2583 ICONST(d, iptr[1].val.i);
2585 if ((s3 >= 0) && (s3 <= 255)) {
2586 M_CMOVNE_IMM(s1, s3, d);
2588 ICONST(REG_ITMP3, s3);
2589 M_CMOVNE(s1, REG_ITMP3, d);
2591 store_reg_to_var_int(iptr->dst, d);
2594 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2595 /* val.i = constant */
2597 var_to_reg_int(s1, src, REG_ITMP1);
2598 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2600 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2601 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2602 M_CMPLT(s1, REG_ZERO, d);
2603 store_reg_to_var_int(iptr->dst, d);
2606 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2607 M_CMPLE(REG_ZERO, s1, d);
2608 store_reg_to_var_int(iptr->dst, d);
2612 M_MOV(s1, REG_ITMP1);
2615 ICONST(d, iptr[1].val.i);
2617 if ((s3 >= 0) && (s3 <= 255)) {
2618 M_CMOVLT_IMM(s1, s3, d);
2620 ICONST(REG_ITMP3, s3);
2621 M_CMOVLT(s1, REG_ITMP3, d);
2623 store_reg_to_var_int(iptr->dst, d);
2626 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2627 /* val.i = constant */
2629 var_to_reg_int(s1, src, REG_ITMP1);
2630 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2632 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2633 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2634 M_CMPLE(REG_ZERO, s1, d);
2635 store_reg_to_var_int(iptr->dst, d);
2638 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2639 M_CMPLT(s1, REG_ZERO, d);
2640 store_reg_to_var_int(iptr->dst, d);
2644 M_MOV(s1, REG_ITMP1);
2647 ICONST(d, iptr[1].val.i);
2649 if ((s3 >= 0) && (s3 <= 255)) {
2650 M_CMOVGE_IMM(s1, s3, d);
2652 ICONST(REG_ITMP3, s3);
2653 M_CMOVGE(s1, REG_ITMP3, d);
2655 store_reg_to_var_int(iptr->dst, d);
2658 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2659 /* val.i = constant */
2661 var_to_reg_int(s1, src, REG_ITMP1);
2662 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2664 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2665 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2666 M_CMPLT(REG_ZERO, s1, d);
2667 store_reg_to_var_int(iptr->dst, d);
2670 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2671 M_CMPLE(s1, REG_ZERO, d);
2672 store_reg_to_var_int(iptr->dst, d);
2676 M_MOV(s1, REG_ITMP1);
2679 ICONST(d, iptr[1].val.i);
2681 if ((s3 >= 0) && (s3 <= 255)) {
2682 M_CMOVGT_IMM(s1, s3, d);
2684 ICONST(REG_ITMP3, s3);
2685 M_CMOVGT(s1, REG_ITMP3, d);
2687 store_reg_to_var_int(iptr->dst, d);
2690 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2691 /* val.i = constant */
2693 var_to_reg_int(s1, src, REG_ITMP1);
2694 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2696 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2697 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2698 M_CMPLE(s1, REG_ZERO, d);
2699 store_reg_to_var_int(iptr->dst, d);
2702 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2703 M_CMPLT(REG_ZERO, s1, d);
2704 store_reg_to_var_int(iptr->dst, d);
2708 M_MOV(s1, REG_ITMP1);
2711 ICONST(d, iptr[1].val.i);
2713 if ((s3 >= 0) && (s3 <= 255)) {
2714 M_CMOVLE_IMM(s1, s3, d);
2716 ICONST(REG_ITMP3, s3);
2717 M_CMOVLE(s1, REG_ITMP3, d);
2719 store_reg_to_var_int(iptr->dst, d);
2724 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2727 var_to_reg_int(s1, src, REG_RESULT);
2728 M_INTMOVE(s1, REG_RESULT);
2729 goto nowperformreturn;
2731 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2733 var_to_reg_int(s1, src, REG_RESULT);
2734 M_INTMOVE(s1, REG_RESULT);
2736 #ifdef ENABLE_VERIFIER
2738 codegen_addpatchref(cd, mcodeptr,
2739 PATCHER_athrow_areturn,
2740 (unresolved_class *) iptr->val.a, 0);
2742 if (opt_showdisassemble) {
2746 #endif /* ENABLE_VERIFIER */
2747 goto nowperformreturn;
2749 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2751 var_to_reg_flt(s1, src, REG_FRESULT);
2753 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2754 M_TFLTMOVE(t, s1, REG_FRESULT);
2756 goto nowperformreturn;
2758 case ICMD_RETURN: /* ... ==> ... */
2764 p = parentargs_base;
2766 /* call trace function */
2768 if (opt_verbosecall) {
2769 M_LDA(REG_SP, REG_SP, -3 * 8);
2770 M_LST(REG_RA, REG_SP, 0 * 8);
2771 M_LST(REG_RESULT, REG_SP, 1 * 8);
2772 M_DST(REG_FRESULT, REG_SP, 2 * 8);
2774 disp = dseg_addaddress(cd, m);
2775 M_ALD(rd->argintregs[0], REG_PV, disp);
2776 M_MOV(REG_RESULT, rd->argintregs[1]);
2777 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2778 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
2780 disp = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2781 M_ALD(REG_ITMP3, REG_PV, disp);
2782 M_JSR(REG_RA, REG_ITMP3);
2785 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
2786 M_LLD(REG_RESULT, REG_SP, 1 * 8);
2787 M_LLD(REG_RA, REG_SP, 0 * 8);
2788 M_LDA(REG_SP, REG_SP, 3 * 8);
2791 #if defined(USE_THREADS)
2792 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2793 disp = dseg_addaddress(cd, (void *) builtin_monitorexit);
2794 M_ALD(REG_ITMP3, REG_PV, disp);
2796 /* we need to save the proper return value */
2798 switch (iptr->opc) {
2802 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2803 M_JSR(REG_RA, REG_ITMP3);
2804 M_LST(REG_RESULT, REG_SP, rd->memuse * 8); /* delay slot */
2808 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2809 M_JSR(REG_RA, REG_ITMP3);
2810 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8); /* delay slot */
2813 M_JSR(REG_RA, REG_ITMP3);
2814 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8); /* delay*/
2818 /* and now restore the proper return value */
2820 switch (iptr->opc) {
2824 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
2828 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
2834 /* restore return address */
2836 if (!m->isleafmethod) {
2837 p--; M_ALD(REG_RA, REG_SP, p * 8);
2840 /* restore saved registers */
2842 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2843 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
2845 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2846 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2849 /* deallocate stack and return */
2851 if (parentargs_base) {
2854 disp = parentargs_base * 8;
2855 lo = (short) (disp);
2856 hi = (short) (((disp) - lo) >> 16);
2860 M_LADD_IMM(REG_SP, lo, REG_SP); /* delay slot */
2862 M_LUI(REG_ITMP3,hi);
2863 M_LADD_IMM(REG_ITMP3,lo,REG_ITMP3);
2865 M_LADD(REG_ITMP3,REG_SP,REG_SP); /* delay slot */
2878 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2883 tptr = (void **) iptr->target;
2885 s4ptr = iptr->val.a;
2886 l = s4ptr[1]; /* low */
2887 i = s4ptr[2]; /* high */
2889 var_to_reg_int(s1, src, REG_ITMP1);
2891 {M_INTMOVE(s1, REG_ITMP1);}
2892 else if (l <= 32768) {
2893 M_IADD_IMM(s1, -l, REG_ITMP1);
2896 ICONST(REG_ITMP2, l);
2897 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2903 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
2904 M_BEQZ(REG_ITMP2, 0);
2905 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2906 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
2908 /* build jump table top down and use address of lowest entry */
2910 /* s4ptr += 3 + i; */
2914 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2915 dseg_addtarget(cd, (basicblock *) tptr[0]);
2920 /* length of dataseg after last dseg_addtarget is used by load */
2922 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2923 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2930 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2932 s4 i, /*l, */val, *s4ptr;
2935 tptr = (void **) iptr->target;
2937 s4ptr = iptr->val.a;
2938 /*l = s4ptr[0];*/ /* default */
2939 i = s4ptr[1]; /* count */
2941 MCODECHECK((i<<2)+8);
2942 var_to_reg_int(s1, src, REG_ITMP1);
2948 ICONST(REG_ITMP2, val);
2949 M_BEQ(s1, REG_ITMP2, 0);
2950 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2955 tptr = (void **) iptr->target;
2956 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2963 case ICMD_BUILTIN: /* ..., arg1 ==> ... */
2964 /* op1 = arg count val.a = builtintable entry */
2970 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2971 /* op1 = arg count, val.a = method pointer */
2973 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2974 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2975 case ICMD_INVOKEINTERFACE:
2980 unresolved_method *um = iptr->target;
2981 md = um->methodref->parseddesc.md;
2983 md = lm->parseddesc;
2987 s3 = md->paramcount;
2989 MCODECHECK((s3 << 1) + 64);
2991 /* copy arguments to registers or stack location */
2993 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2994 if (src->varkind == ARGVAR)
2996 if (IS_INT_LNG_TYPE(src->type)) {
2997 if (!md->params[s3].inmemory) {
2998 s1 = rd->argintregs[md->params[s3].regoff];
2999 var_to_reg_int(d, src, s1);
3002 var_to_reg_int(d, src, REG_ITMP1);
3003 M_LST(d, REG_SP, md->params[s3].regoff * 8);
3007 if (!md->params[s3].inmemory) {
3008 s1 = rd->argfltregs[md->params[s3].regoff];
3009 var_to_reg_flt(d, src, s1);
3010 M_TFLTMOVE(src->type, d, s1);
3012 var_to_reg_flt(d, src, REG_FTMP1);
3013 M_DST(d, REG_SP, md->params[s3].regoff * 8);
3018 switch (iptr->opc) {
3020 disp = dseg_addaddress(cd, bte->fp);
3021 d = md->returntype.type;
3023 M_ALD(REG_ITMP3, REG_PV, disp); /* built-in-function pointer */
3024 M_JSR(REG_RA, REG_ITMP3);
3026 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3027 M_LDA(REG_PV, REG_RA, -disp);
3029 /* if op1 == true, we need to check for an exception */
3031 if (iptr->op1 == true) {
3032 M_BEQZ(REG_RESULT, 0);
3033 codegen_add_fillinstacktrace_ref(cd, mcodeptr);
3038 case ICMD_INVOKESPECIAL:
3039 M_BEQZ(rd->argintregs[0], 0);
3040 codegen_add_nullpointerexception_ref(cd, mcodeptr);
3044 case ICMD_INVOKESTATIC:
3046 unresolved_method *um = iptr->target;
3048 disp = dseg_addaddress(cd, NULL);
3050 codegen_addpatchref(cd, mcodeptr,
3051 PATCHER_invokestatic_special, um, disp);
3053 if (opt_showdisassemble) {
3057 d = um->methodref->parseddesc.md->returntype.type;
3060 disp = dseg_addaddress(cd, lm->stubroutine);
3061 d = lm->parseddesc->returntype.type;
3064 M_ALD(REG_PV, REG_PV, disp); /* method pointer in pv */
3065 M_JSR(REG_RA, REG_PV);
3067 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3068 M_LDA(REG_PV, REG_RA, -disp);
3071 case ICMD_INVOKEVIRTUAL:
3072 gen_nullptr_check(rd->argintregs[0]);
3075 unresolved_method *um = iptr->target;
3077 codegen_addpatchref(cd, mcodeptr,
3078 PATCHER_invokevirtual, um, 0);
3080 if (opt_showdisassemble) {
3085 d = um->methodref->parseddesc.md->returntype.type;
3088 s1 = OFFSET(vftbl_t, table[0]) +
3089 sizeof(methodptr) * lm->vftblindex;
3090 d = lm->parseddesc->returntype.type;
3093 M_ALD(REG_METHODPTR, rd->argintregs[0],
3094 OFFSET(java_objectheader, vftbl));
3095 M_ALD(REG_PV, REG_METHODPTR, s1);
3096 M_JSR(REG_RA, REG_PV);
3098 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3099 M_LDA(REG_PV, REG_RA, -disp);
3102 case ICMD_INVOKEINTERFACE:
3103 gen_nullptr_check(rd->argintregs[0]);
3106 unresolved_method *um = iptr->target;
3108 codegen_addpatchref(cd, mcodeptr,
3109 PATCHER_invokeinterface, um, 0);
3111 if (opt_showdisassemble) {
3117 d = um->methodref->parseddesc.md->returntype.type;
3120 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3121 sizeof(methodptr*) * lm->class->index;
3123 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3125 d = lm->parseddesc->returntype.type;
3128 M_ALD(REG_METHODPTR, rd->argintregs[0],
3129 OFFSET(java_objectheader, vftbl));
3130 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3131 M_ALD(REG_PV, REG_METHODPTR, s2);
3132 M_JSR(REG_RA, REG_PV);
3134 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3135 M_LDA(REG_PV, REG_RA, -disp);
3139 /* d contains return type */
3141 if (d != TYPE_VOID) {
3142 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3143 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3144 M_INTMOVE(REG_RESULT, s1);
3145 store_reg_to_var_int(iptr->dst, s1);
3147 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3148 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3149 store_reg_to_var_flt(iptr->dst, s1);
3155 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3156 /* op1: 0 == array, 1 == class */
3157 /* val.a: (classinfo*) superclass */
3159 /* superclass is an interface:
3161 * OK if ((sub == NULL) ||
3162 * (sub->vftbl->interfacetablelength > super->index) &&
3163 * (sub->vftbl->interfacetable[-super->index] != NULL));
3165 * superclass is a class:
3167 * OK if ((sub == NULL) || (0
3168 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3169 * super->vftbl->diffvall));
3172 if (iptr->op1 == 1) {
3174 vftbl_t *supervftbl;
3177 super = (classinfo *) iptr->val.a;
3184 superindex = super->index;
3185 supervftbl = super->vftbl;
3188 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3189 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3192 var_to_reg_int(s1, src, REG_ITMP1);
3194 /* calculate interface checkcast code size */
3198 s2 += (opt_showdisassemble ? 2 : 0);
3200 /* calculate class checkcast code size */
3202 s3 = 10 /* 10 + (s1 == REG_ITMP1) */;
3204 s3 += (opt_showdisassemble ? 2 : 0);
3206 /* if class is not resolved, check which code to call */
3209 M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
3212 disp = dseg_adds4(cd, 0); /* super->flags */
3214 codegen_addpatchref(cd, mcodeptr,
3215 PATCHER_checkcast_instanceof_flags,
3216 (constant_classref *) iptr->target,
3219 if (opt_showdisassemble) {
3223 /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
3224 M_ILD(REG_ITMP2, REG_PV, disp);
3225 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3226 M_BEQZ(REG_ITMP2, 1 + s2 + 2);
3230 /* interface checkcast code */
3232 if (!super || super->flags & ACC_INTERFACE) {
3238 codegen_addpatchref(cd, mcodeptr,
3239 PATCHER_checkcast_instanceof_interface,
3240 (constant_classref *) iptr->target,
3243 if (opt_showdisassemble) {
3248 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3249 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3250 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3251 M_BLEZ(REG_ITMP3, 0);
3252 codegen_add_classcastexception_ref(cd, mcodeptr);
3254 M_ALD(REG_ITMP3, REG_ITMP2,
3255 OFFSET(vftbl_t, interfacetable[0]) -
3256 superindex * sizeof(methodptr*));
3257 M_BEQZ(REG_ITMP3, 0);
3258 codegen_add_classcastexception_ref(cd, mcodeptr);
3267 /* class checkcast code */
3269 if (!super || !(super->flags & ACC_INTERFACE)) {
3270 disp = dseg_addaddress(cd, (void *) supervftbl);
3277 codegen_addpatchref(cd, mcodeptr,
3278 PATCHER_checkcast_instanceof_class,
3279 (constant_classref *) iptr->target,
3282 if (opt_showdisassemble) {
3287 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3288 M_ALD(REG_ITMP3, REG_PV, disp);
3289 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3290 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3292 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3293 /* if (s1 != REG_ITMP1) { */
3294 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3295 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3296 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3297 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3299 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3301 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3302 M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3303 M_ALD(REG_ITMP3, REG_PV, disp);
3304 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3305 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3306 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3309 M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3310 M_BNEZ(REG_ITMP3, 0);
3311 codegen_add_classcastexception_ref(cd, mcodeptr);
3314 d = reg_of_var(rd, iptr->dst, s1);
3317 var_to_reg_int(s1, src, rd->argintregs[0]);
3318 M_INTMOVE(s1, rd->argintregs[0]);
3320 disp = dseg_addaddress(cd, iptr->val.a);
3322 if (iptr->val.a == NULL) {
3323 codegen_addpatchref(cd, mcodeptr,
3324 PATCHER_builtin_arraycheckcast,
3325 (constant_classref *) iptr->target,
3328 if (opt_showdisassemble) {
3333 M_ALD(rd->argintregs[1], REG_PV, disp);
3334 disp = dseg_addaddress(cd, BUILTIN_arraycheckcast);
3335 M_ALD(REG_ITMP3, REG_PV, disp);
3336 M_JSR(REG_RA, REG_ITMP3);
3339 M_BEQZ(REG_RESULT, 0);
3340 codegen_add_classcastexception_ref(cd, mcodeptr);
3343 var_to_reg_int(s1, src, REG_ITMP1);
3344 d = reg_of_var(rd, iptr->dst, s1);
3347 store_reg_to_var_int(iptr->dst, d);
3350 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3351 /* op1: 0 == array, 1 == class */
3352 /* val.a: (classinfo*) superclass */
3354 /* superclass is an interface:
3356 * return (sub != NULL) &&
3357 * (sub->vftbl->interfacetablelength > super->index) &&
3358 * (sub->vftbl->interfacetable[-super->index] != NULL);
3360 * superclass is a class:
3362 * return ((sub != NULL) && (0
3363 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3364 * super->vftbl->diffvall));
3369 vftbl_t *supervftbl;
3372 super = (classinfo *) iptr->val.a;
3379 superindex = super->index;
3380 supervftbl = super->vftbl;
3383 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3384 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3387 var_to_reg_int(s1, src, REG_ITMP1);
3388 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3390 M_MOV(s1, REG_ITMP1);
3394 /* calculate interface instanceof code size */
3398 s2 += (opt_showdisassemble ? 2 : 0);
3400 /* calculate class instanceof code size */
3404 s3 += (opt_showdisassemble ? 2 : 0);
3408 /* if class is not resolved, check which code to call */
3411 M_BEQZ(s1, 5 + (opt_showdisassemble ? 2 : 0) + s2 + 2 + s3);
3414 disp = dseg_adds4(cd, 0); /* super->flags */
3416 codegen_addpatchref(cd, mcodeptr,
3417 PATCHER_checkcast_instanceof_flags,
3418 (constant_classref *) iptr->target, disp);
3420 if (opt_showdisassemble) {
3424 /* XXX TWISTI M_ILD can be 2 instructions long (jump offset) */
3425 M_ILD(REG_ITMP3, REG_PV, disp);
3426 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
3427 M_BEQZ(REG_ITMP3, 1 + s2 + 2);
3431 /* interface instanceof code */
3433 if (!super || (super->flags & ACC_INTERFACE)) {
3439 codegen_addpatchref(cd, mcodeptr,
3440 PATCHER_checkcast_instanceof_interface,
3441 (constant_classref *) iptr->target, 0);
3443 if (opt_showdisassemble) {
3448 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3449 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3450 M_IADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
3451 M_BLEZ(REG_ITMP3, 3);
3453 M_ALD(REG_ITMP1, REG_ITMP1,
3454 OFFSET(vftbl_t, interfacetable[0]) -
3455 superindex * sizeof(methodptr*));
3456 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3464 /* class instanceof code */
3466 if (!super || !(super->flags & ACC_INTERFACE)) {
3467 disp = dseg_addaddress(cd, supervftbl);
3474 codegen_addpatchref(cd, mcodeptr,
3475 PATCHER_checkcast_instanceof_class,
3476 (constant_classref *) iptr->target,
3479 if (opt_showdisassemble) {
3484 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3485 M_ALD(REG_ITMP2, REG_PV, disp);
3486 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3487 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3489 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3490 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3491 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3492 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3493 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3495 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3496 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3499 store_reg_to_var_int(iptr->dst, d);
3503 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3504 /* op1 = dimension, val.a = class */
3506 /* check for negative sizes and copy sizes to stack if necessary */
3508 MCODECHECK((iptr->op1 << 1) + 64);
3510 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3511 /* copy SAVEDVAR sizes to stack */
3513 if (src->varkind != ARGVAR) {
3514 var_to_reg_int(s2, src, REG_ITMP1);
3515 M_LST(s2, REG_SP, s1 * 8);
3519 /* a0 = dimension count */
3521 ICONST(rd->argintregs[0], iptr->op1);
3523 /* is patcher function set? */
3525 if (iptr->val.a == NULL) {
3526 disp = dseg_addaddress(cd, NULL);
3528 codegen_addpatchref(cd, mcodeptr,
3529 PATCHER_builtin_multianewarray,
3530 (constant_classref *) iptr->target,
3533 if (opt_showdisassemble) {
3538 disp = dseg_addaddress(cd, iptr->val.a);
3541 /* a1 = arraydescriptor */
3543 M_ALD(rd->argintregs[1], REG_PV, disp);
3545 /* a2 = pointer to dimensions = stack pointer */
3547 M_INTMOVE(REG_SP, rd->argintregs[2]);
3549 disp = dseg_addaddress(cd, BUILTIN_multianewarray);
3550 M_ALD(REG_ITMP3, REG_PV, disp);
3551 M_JSR(REG_RA, REG_ITMP3);
3554 /* check for exception before result assignment */
3556 M_BEQZ(REG_RESULT, 0);
3557 codegen_add_fillinstacktrace_ref(cd, mcodeptr);
3560 d = reg_of_var(rd, iptr->dst, REG_RESULT);
3561 M_INTMOVE(REG_RESULT, d);
3562 store_reg_to_var_int(iptr->dst, d);
3566 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3570 } /* for instruction */
3572 /* copy values to interface registers */
3574 src = bptr->outstack;
3575 len = bptr->outdepth;
3577 #if defined(ENABLE_LSRA)
3582 if ((src->varkind != STACKVAR)) {
3584 if (IS_FLT_DBL_TYPE(s2)) {
3585 var_to_reg_flt(s1, src, REG_FTMP1);
3586 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3587 M_TFLTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3590 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3594 var_to_reg_int(s1, src, REG_ITMP1);
3595 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3596 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3599 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3606 /* At the end of a basic block we may have to append some nops,
3607 because the patcher stub calling code might be longer than the
3608 actual instruction. So codepatching does not change the
3609 following block unintentionally. */
3611 if ((u1 *) mcodeptr < cd->lastmcodeptr) {
3612 while ((u1 *) mcodeptr < cd->lastmcodeptr) {
3617 } /* if (bptr -> flags >= BBREACHED) */
3618 } /* for basic block */
3620 dseg_createlinenumbertable(cd);
3627 /* generate ArithmeticException stubs */
3631 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3632 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3634 (u1 *) mcodeptr - cd->mcodebase);
3638 if (xcodeptr != NULL) {
3639 M_BR(xcodeptr - mcodeptr);
3640 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3643 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3645 xcodeptr = mcodeptr;
3647 M_MOV(REG_PV, rd->argintregs[0]);
3648 M_MOV(REG_SP, rd->argintregs[1]);
3650 if (m->isleafmethod)
3651 M_MOV(REG_RA, rd->argintregs[2]);
3653 M_ALD(rd->argintregs[2],
3654 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3656 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3658 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3659 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3661 if (m->isleafmethod)
3662 M_AST(REG_RA, REG_SP, 1 * 8);
3664 a = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
3665 M_ALD(REG_ITMP3, REG_PV, a);
3666 M_JSR(REG_RA, REG_ITMP3);
3668 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3670 if (m->isleafmethod)
3671 M_ALD(REG_RA, REG_SP, 1 * 8);
3673 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3674 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3676 a = dseg_addaddress(cd, asm_handle_exception);
3677 M_ALD(REG_ITMP3, REG_PV, a);
3683 /* generate ArrayIndexOutOfBoundsException stubs */
3687 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3688 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3690 (u1 *) mcodeptr - cd->mcodebase);
3694 /* move index register into REG_ITMP1 */
3696 M_MOV(bref->reg, REG_ITMP1);
3697 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3699 if (xcodeptr != NULL) {
3700 M_BR(xcodeptr - mcodeptr);
3704 xcodeptr = mcodeptr;
3706 M_MOV(REG_PV, rd->argintregs[0]);
3707 M_MOV(REG_SP, rd->argintregs[1]);
3709 if (m->isleafmethod)
3710 M_MOV(REG_RA, rd->argintregs[2]);
3712 M_ALD(rd->argintregs[2],
3713 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3715 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3716 M_MOV(REG_ITMP1, rd->argintregs[4]);
3718 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3719 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3721 if (m->isleafmethod)
3722 M_AST(REG_RA, REG_SP, 1 * 8);
3724 a = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
3725 M_ALD(REG_ITMP3, REG_PV, a);
3726 M_JSR(REG_RA, REG_ITMP3);
3728 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3730 if (m->isleafmethod)
3731 M_ALD(REG_RA, REG_SP, 1 * 8);
3733 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3734 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3736 a = dseg_addaddress(cd, asm_handle_exception);
3737 M_ALD(REG_ITMP3, REG_PV, a);
3743 /* generate ArrayStoreException stubs */
3747 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
3748 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3750 (u1 *) mcodeptr - cd->mcodebase);
3754 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3756 if (xcodeptr != NULL) {
3757 M_BR(xcodeptr - mcodeptr);
3761 xcodeptr = mcodeptr;
3763 M_MOV(REG_PV, rd->argintregs[0]);
3764 M_MOV(REG_SP, rd->argintregs[1]);
3765 M_ALD(rd->argintregs[2],
3766 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3767 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3769 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3770 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3772 a = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
3773 M_ALD(REG_ITMP3, REG_PV, a);
3774 M_JSR(REG_RA, REG_ITMP3);
3776 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3778 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3779 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3781 a = dseg_addaddress(cd, asm_handle_exception);
3782 M_ALD(REG_ITMP3, REG_PV, a);
3788 /* generate ClassCastException stubs */
3792 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3793 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3795 (u1 *) mcodeptr - cd->mcodebase);
3799 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3801 if (xcodeptr != NULL) {
3802 M_BR(xcodeptr - mcodeptr);
3806 xcodeptr = mcodeptr;
3808 M_MOV(REG_PV, rd->argintregs[0]);
3809 M_MOV(REG_SP, rd->argintregs[1]);
3811 if (m->isleafmethod)
3812 M_MOV(REG_RA, rd->argintregs[2]);
3814 M_ALD(rd->argintregs[2],
3815 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3817 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3819 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3820 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3822 if (m->isleafmethod)
3823 M_AST(REG_RA, REG_SP, 1 * 8);
3825 a = dseg_addaddress(cd, stacktrace_inline_classcastexception);
3826 M_ALD(REG_ITMP3, REG_PV, a);
3827 M_JSR(REG_RA, REG_ITMP3);
3829 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3831 if (m->isleafmethod)
3832 M_ALD(REG_RA, REG_SP, 1 * 8);
3834 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3835 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3837 a = dseg_addaddress(cd, asm_handle_exception);
3838 M_ALD(REG_ITMP3, REG_PV, a);
3844 /* generate NullPointerException stubs */
3848 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3849 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3851 (u1 *) mcodeptr - cd->mcodebase);
3855 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3857 if (xcodeptr != NULL) {
3858 M_BR(xcodeptr - mcodeptr);
3862 xcodeptr = mcodeptr;
3864 M_MOV(REG_PV, rd->argintregs[0]);
3865 M_MOV(REG_SP, rd->argintregs[1]);
3867 if (m->isleafmethod)
3868 M_MOV(REG_RA, rd->argintregs[2]);
3870 M_ALD(rd->argintregs[2],
3871 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3873 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3875 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
3876 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3878 if (m->isleafmethod)
3879 M_AST(REG_RA, REG_SP, 1 * 8);
3881 a = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
3882 M_ALD(REG_ITMP3, REG_PV, a);
3883 M_JSR(REG_RA, REG_ITMP3);
3885 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3887 if (m->isleafmethod)
3888 M_ALD(REG_RA, REG_SP, 1 * 8);
3890 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3891 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
3893 a = dseg_addaddress(cd, asm_handle_exception);
3894 M_ALD(REG_ITMP3, REG_PV, a);
3900 /* generate exception check stubs */
3904 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3905 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3907 (u1 *) mcodeptr - cd->mcodebase);
3911 if (xcodeptr != NULL) {
3912 M_BR(xcodeptr - mcodeptr);
3913 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC); /* delay */
3916 M_AADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3918 xcodeptr = mcodeptr;
3920 M_MOV(REG_PV, rd->argintregs[0]);
3921 M_MOV(REG_SP, rd->argintregs[1]);
3922 M_ALD(rd->argintregs[2],
3923 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3924 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3926 M_ASUB_IMM(REG_SP, 1 * 8, REG_SP);
3927 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3929 a = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
3930 M_ALD(REG_ITMP3, REG_PV, a);
3931 M_JSR(REG_RA, REG_ITMP3);
3933 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3935 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3936 M_AADD_IMM(REG_SP, 1 * 8, REG_SP);
3938 a = dseg_addaddress(cd, asm_handle_exception);
3939 M_ALD(REG_ITMP3, REG_PV, a);
3947 /* generate exception and patcher stubs */
3956 savedmcodeptr = NULL;
3958 /* generate exception stubs */
3960 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
3961 gen_resolvebranch((u1 *) cd->mcodebase + eref->branchpos,
3963 (u1 *) mcodeptr - cd->mcodebase);
3967 /* Check if the exception is an
3968 ArrayIndexOutOfBoundsException. If so, move index register
3971 if (eref->reg != -1)
3972 M_MOV(eref->reg, REG_ITMP1);
3974 /* calcuate exception address */
3976 M_LDA(REG_ITMP2_XPC, REG_PV, eref->branchpos - 4);
3978 /* move function to call into REG_ITMP3 */
3980 disp = dseg_addaddress(cd, eref->function);
3981 M_ALD(REG_ITMP3, REG_PV, disp);
3983 if (savedmcodeptr != NULL) {
3984 M_BR(savedmcodeptr - mcodeptr);
3988 savedmcodeptr = mcodeptr;
3990 M_MOV(REG_PV, rd->argintregs[0]);
3991 M_MOV(REG_SP, rd->argintregs[1]);
3993 if (m->isleafmethod)
3994 M_MOV(REG_RA, rd->argintregs[2]);
3996 M_ALD(rd->argintregs[2],
3997 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3999 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
4000 M_MOV(REG_ITMP1, rd->argintregs[4]);
4002 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
4003 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
4005 if (m->isleafmethod)
4006 M_AST(REG_RA, REG_SP, 1 * 8);
4008 M_JSR(REG_RA, REG_ITMP3);
4010 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
4012 if (m->isleafmethod)
4013 M_ALD(REG_RA, REG_SP, 1 * 8);
4015 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
4016 M_AADD_IMM(REG_SP, 2 * 8, REG_SP);
4018 a = dseg_addaddress(cd, asm_handle_exception);
4019 M_ALD(REG_ITMP3, REG_PV, a);
4026 /* generate code patching stub call code */
4028 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4029 /* check code segment size */
4033 /* Get machine code which is patched back in later. The
4034 call is 2 instruction words long. */
4036 tmpmcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4038 /* We need to split this, because an unaligned 8 byte read
4039 causes a SIGSEGV. */
4041 mcode = ((u8) tmpmcodeptr[1] << 32) + (u4) tmpmcodeptr[0];
4043 /* Patch in the call to call the following code (done at
4046 savedmcodeptr = mcodeptr; /* save current mcodeptr */
4047 mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
4049 disp = (s4) (savedmcodeptr - (tmpmcodeptr + 1));
4051 if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) {
4053 new_internalerror("Jump offset is out of range: %d > +/-%d",
4061 mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
4063 /* create stack frame */
4065 M_ASUB_IMM(REG_SP, 6 * 8, REG_SP);
4067 /* calculate return address and move it onto the stack */
4069 M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
4070 M_AST(REG_ITMP3, REG_SP, 5 * 8);
4072 /* move pointer to java_objectheader onto stack */
4074 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4075 /* create a virtual java_objectheader */
4077 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4078 disp = dseg_addaddress(cd, NULL); /* vftbl */
4080 M_LDA(REG_ITMP3, REG_PV, disp);
4081 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4086 /* move machine code onto stack */
4088 disp = dseg_adds8(cd, mcode);
4089 M_LLD(REG_ITMP3, REG_PV, disp);
4090 M_LST(REG_ITMP3, REG_SP, 3 * 8);
4092 /* move class/method/field reference onto stack */
4094 disp = dseg_addaddress(cd, pref->ref);
4095 M_ALD(REG_ITMP3, REG_PV, disp);
4096 M_AST(REG_ITMP3, REG_SP, 2 * 8);
4098 /* move data segment displacement onto stack */
4100 disp = dseg_adds4(cd, pref->disp);
4101 M_ILD(REG_ITMP3, REG_PV, disp);
4102 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4104 /* move patcher function pointer onto stack */
4106 disp = dseg_addaddress(cd, pref->patcher);
4107 M_ALD(REG_ITMP3, REG_PV, disp);
4108 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4110 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4111 M_ALD(REG_ITMP3, REG_PV, disp);
4116 /* generate replacement-out stubs */
4121 replacementpoint = cd->code->rplpoints;
4122 for (i=0; i<cd->code->rplpointcount; ++i, ++replacementpoint) {
4123 /* check code segment size */
4127 /* note start of stub code */
4129 replacementpoint->outcode = (u1*) (ptrint)((u1*)mcodeptr - cd->mcodebase);
4131 /* make machine code for patching */
4133 tmpmcodeptr = mcodeptr;
4134 mcodeptr = (s4*) &(replacementpoint->mcode);
4136 disp = (ptrint)((s4*)replacementpoint->outcode - (s4*)replacementpoint->pc) - 1;
4137 if ((disp < (s4) 0xffff8000) || (disp > (s4) 0x00007fff)) {
4139 new_internalerror("Jump offset is out of range: %d > +/-%d",
4144 M_NOP; /* delay slot */
4146 mcodeptr = tmpmcodeptr;
4148 /* create stack frame - 16-byte aligned */
4150 M_ASUB_IMM(REG_SP, 2 * 8, REG_SP);
4152 /* push address of `rplpoint` struct */
4154 disp = dseg_addaddress(cd, replacementpoint);
4155 M_ALD(REG_ITMP3, REG_PV, disp);
4156 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4158 /* jump to replacement function */
4160 disp = dseg_addaddress(cd, asm_replacement_out);
4161 M_ALD(REG_ITMP3, REG_PV, disp);
4163 M_NOP; /* delay slot */
4168 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4170 docacheflush((void *) cd->code->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4172 /* everything's ok */
4178 /* createcompilerstub **********************************************************
4180 Creates a stub routine which calls the compiler.
4182 *******************************************************************************/
4184 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
4185 #define COMPILERSTUB_CODESIZE 4 * 4
4187 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4190 u1 *createcompilerstub(methodinfo *m)
4192 u1 *s; /* memory to hold the stub */
4194 s4 *mcodeptr; /* code generation pointer */
4196 s = CNEW(u1, COMPILERSTUB_SIZE);
4198 /* set data pointer and code pointer */
4201 s = s + COMPILERSTUB_DATASIZE;
4203 mcodeptr = (s4 *) s;
4205 /* Store the methodinfo* in the same place as in the methodheader
4206 for compiled methods. */
4208 d[0] = (ptrint) asm_call_jit_compiler;
4211 M_ALD_INTERN(REG_ITMP1, REG_PV, -1 * SIZEOF_VOID_P); /* method pointer */
4212 M_ALD_INTERN(REG_PV, REG_PV, -2 * SIZEOF_VOID_P); /* pointer to compiler */
4216 (void) docacheflush((void *) s, (char *) mcodeptr - (char *) s);
4218 #if defined(ENABLE_STATISTICS)
4220 count_cstub_len += COMPILERSTUB_SIZE;
4227 /* createnativestub ************************************************************
4229 Creates a stub routine which calls a native method.
4231 *******************************************************************************/
4233 u1 *createnativestub(functionptr f, methodinfo *m, codegendata *cd,
4234 registerdata *rd, methoddesc *nmd)
4236 s4 *mcodeptr; /* code generation pointer */
4237 s4 stackframesize; /* size of stackframe if needed */
4240 s4 i, j; /* count variables */
4243 s4 funcdisp; /* displacement of the function */
4246 /* initialize variables */
4249 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4252 /* calculate stack frame size */
4255 1 + /* return address */
4256 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4257 sizeof(localref_table) / SIZEOF_VOID_P +
4258 md->paramcount + /* for saving arguments over calls */
4259 1 + /* for saving return address */
4263 /* create method header */
4265 #if SIZEOF_VOID_P == 4
4266 (void) dseg_addaddress(cd, m); /* MethodPointer */
4268 (void) dseg_addaddress(cd, m); /* MethodPointer */
4269 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4270 (void) dseg_adds4(cd, 0); /* IsSync */
4271 (void) dseg_adds4(cd, 0); /* IsLeaf */
4272 (void) dseg_adds4(cd, 0); /* IntSave */
4273 (void) dseg_adds4(cd, 0); /* FltSave */
4274 (void) dseg_addlinenumbertablesize(cd);
4275 (void) dseg_adds4(cd, 0); /* ExTableSize */
4278 /* initialize mcode variables */
4280 mcodeptr = (s4 *) cd->mcodeptr;
4283 /* generate stub code */
4285 M_LDA(REG_SP, REG_SP, -stackframesize * 8); /* build up stackframe */
4286 M_AST(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* store ra */
4289 /* call trace function */
4291 if (opt_verbosecall) {
4292 M_LDA(REG_SP, REG_SP, -(1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4294 /* save integer argument registers */
4296 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4297 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4298 M_LST(rd->argintregs[i], REG_SP, (1 + i) * 8);
4300 /* save and copy float arguments into integer registers */
4302 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4303 t = md->paramtypes[i].type;
4305 if (IS_FLT_DBL_TYPE(t)) {
4306 if (IS_2_WORD_TYPE(t)) {
4307 M_DST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4308 M_LLD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4310 M_FST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4311 M_ILD(rd->argintregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4316 disp = dseg_addaddress(cd, m);
4317 M_ALD(REG_ITMP1, REG_PV, disp);
4318 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4319 disp = dseg_addaddress(cd, builtin_trace_args);
4320 M_ALD(REG_ITMP3, REG_PV, disp);
4321 M_JSR(REG_RA, REG_ITMP3);
4324 for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++)
4325 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4326 M_LLD(rd->argintregs[i], REG_SP, (1 + i) * 8);
4328 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4329 t = md->paramtypes[i].type;
4331 if (IS_FLT_DBL_TYPE(t)) {
4332 if (IS_2_WORD_TYPE(t)) {
4333 M_DLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4335 M_FLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4340 M_LDA(REG_SP, REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT) * 8);
4344 /* get function address (this must happen before the stackframeinfo) */
4346 funcdisp = dseg_addaddress(cd, f);
4348 #if !defined(WITH_STATIC_CLASSPATH)
4350 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m, funcdisp);
4352 if (opt_showdisassemble) {
4358 /* save integer and float argument registers */
4360 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4361 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4362 M_LST(rd->argintregs[i], REG_SP, j * 8);
4367 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4368 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4369 M_DST(rd->argfltregs[i], REG_SP, j * 8);
4374 /* prepare data structures for native function call */
4376 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4377 M_MOV(REG_PV, rd->argintregs[1]);
4378 M_AADD_IMM(REG_SP, stackframesize * 8, rd->argintregs[2]);
4379 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8 - SIZEOF_VOID_P);
4380 disp = dseg_addaddress(cd, codegen_start_native_call);
4381 M_ALD(REG_ITMP3, REG_PV, disp);
4382 M_JSR(REG_RA, REG_ITMP3);
4383 M_NOP; /* XXX fill me! */
4385 /* restore integer and float argument registers */
4387 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4388 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4389 M_LLD(rd->argintregs[i], REG_SP, j * 8);
4394 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4395 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4396 M_DLD(rd->argfltregs[i], REG_SP, j * 8);
4401 /* copy or spill arguments to new locations */
4403 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4404 t = md->paramtypes[i].type;
4406 if (IS_INT_LNG_TYPE(t)) {
4407 if (!md->params[i].inmemory) {
4408 s1 = rd->argintregs[md->params[i].regoff];
4410 if (!nmd->params[j].inmemory) {
4411 s2 = rd->argintregs[nmd->params[j].regoff];
4414 s2 = nmd->params[j].regoff;
4415 M_AST(s1, REG_SP, s2 * 8);
4419 s1 = md->params[i].regoff + stackframesize;
4420 s2 = nmd->params[j].regoff;
4421 M_ALD(REG_ITMP1, REG_SP, s1 * 8);
4422 M_AST(REG_ITMP1, REG_SP, s2 * 8);
4426 if (!md->params[i].inmemory) {
4427 s1 = rd->argfltregs[md->params[i].regoff];
4429 if (!nmd->params[j].inmemory) {
4430 s2 = rd->argfltregs[nmd->params[j].regoff];
4431 M_TFLTMOVE(t, s1, s2);
4433 s2 = nmd->params[j].regoff;
4434 if (IS_2_WORD_TYPE(t))
4435 M_DST(s1, REG_SP, s2 * 8);
4437 M_FST(s1, REG_SP, s2 * 8);
4441 s1 = md->params[i].regoff + stackframesize;
4442 s2 = nmd->params[j].regoff;
4443 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4444 if (IS_2_WORD_TYPE(t))
4445 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4447 M_FST(REG_FTMP1, REG_SP, s2 * 8);
4452 /* put class into second argument register */
4454 if (m->flags & ACC_STATIC) {
4455 disp = dseg_addaddress(cd, m->class);
4456 M_ALD(rd->argintregs[1], REG_PV, disp);
4459 /* put env into first argument register */
4461 disp = dseg_addaddress(cd, _Jv_env);
4462 M_ALD(rd->argintregs[0], REG_PV, disp);
4464 /* do the native function call */
4466 M_ALD(REG_ITMP3, REG_PV, funcdisp); /* load adress of native method */
4467 M_JSR(REG_RA, REG_ITMP3); /* call native method */
4468 M_NOP; /* delay slot */
4470 /* save return value */
4472 if (IS_INT_LNG_TYPE(md->returntype.type))
4473 M_LST(REG_RESULT, REG_SP, 0 * 8);
4475 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4477 /* remove native stackframe info */
4479 M_AADD_IMM(REG_SP, stackframesize * 8 - SIZEOF_VOID_P, rd->argintregs[0]);
4480 disp = dseg_addaddress(cd, codegen_finish_native_call);
4481 M_ALD(REG_ITMP3, REG_PV, disp);
4482 M_JSR(REG_RA, REG_ITMP3);
4483 M_NOP; /* XXX fill me! */
4485 /* call finished trace function */
4487 if (opt_verbosecall) {
4488 if (IS_INT_LNG_TYPE(md->returntype.type))
4489 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4491 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4493 disp = dseg_addaddress(cd, m);
4494 M_ALD(rd->argintregs[0], REG_PV, disp);
4496 M_MOV(REG_RESULT, rd->argintregs[1]);
4497 M_DMFC1(REG_ITMP1, REG_FRESULT);
4498 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
4499 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
4501 disp = dseg_addaddress(cd, builtin_displaymethodstop);
4502 M_ALD(REG_ITMP3, REG_PV, disp);
4503 M_JSR(REG_RA, REG_ITMP3);
4507 /* check for exception */
4509 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4510 disp = dseg_addaddress(cd, builtin_get_exceptionptrptr);
4511 M_ALD(REG_ITMP3, REG_PV, disp);
4512 M_JSR(REG_RA, REG_ITMP3);
4514 M_MOV(REG_RESULT, REG_ITMP3);
4516 disp = dseg_addaddress(cd, &_exceptionptr);
4517 M_ALD(REG_ITMP3, REG_PV, disp); /* get address of exceptionptr */
4519 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4521 M_ALD(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P); /* load ra */
4523 /* restore return value */
4525 if (IS_INT_LNG_TYPE(md->returntype.type))
4526 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4528 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4530 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
4531 M_LDA(REG_SP, REG_SP, stackframesize * 8);/* remove stackframe, DELAY SLOT*/
4533 M_RET(REG_RA); /* return to caller */
4534 M_NOP; /* DELAY SLOT */
4536 /* handle exception */
4538 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4540 disp = dseg_addaddress(cd, asm_handle_nat_exception);
4541 M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */
4542 M_JMP(REG_ITMP3); /* jump to asm exception handler */
4543 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4546 /* generate static stub call code */
4554 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4555 /* Get machine code which is patched back in later. The
4556 call is 2 instruction words long. */
4558 tmpmcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4560 /* We need to split this, because an unaligned 8 byte read
4561 causes a SIGSEGV. */
4563 mcode = ((u8) tmpmcodeptr[1] << 32) + (u4) tmpmcodeptr[0];
4565 /* Patch in the call to call the following code (done at
4568 savedmcodeptr = mcodeptr; /* save current mcodeptr */
4569 mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
4571 M_BRS(savedmcodeptr - (tmpmcodeptr + 1));
4572 M_NOP; /* branch delay slot */
4574 mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
4576 /* create stack frame */
4578 M_LSUB_IMM(REG_SP, 6 * 8, REG_SP);
4580 /* move return address onto stack */
4582 M_AST(REG_RA, REG_SP, 5 * 8);
4584 /* move pointer to java_objectheader onto stack */
4586 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4587 /* order reversed because of data segment layout */
4589 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4590 disp = dseg_addaddress(cd, NULL); /* vftbl */
4592 M_LDA(REG_ITMP3, REG_PV, disp);
4593 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4595 M_AST(REG_ZERO, REG_SP, 4 * 8);
4598 /* move machine code onto stack */
4600 disp = dseg_adds8(cd, mcode);
4601 M_LLD(REG_ITMP3, REG_PV, disp);
4602 M_LST(REG_ITMP3, REG_SP, 3 * 8);
4604 /* move class/method/field reference onto stack */
4606 disp = dseg_addaddress(cd, pref->ref);
4607 M_ALD(REG_ITMP3, REG_PV, disp);
4608 M_AST(REG_ITMP3, REG_SP, 2 * 8);
4610 /* move data segment displacement onto stack */
4612 disp = dseg_adds4(cd, pref->disp);
4613 M_ILD(REG_ITMP3, REG_PV, disp);
4614 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4616 /* move patcher function pointer onto stack */
4618 disp = dseg_addaddress(cd, pref->patcher);
4619 M_ALD(REG_ITMP3, REG_PV, disp);
4620 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4622 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4623 M_ALD(REG_ITMP3, REG_PV, disp);
4629 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4631 docacheflush((void *) cd->code->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4633 return cd->code->entrypoint;
4638 * These are local overrides for various environment variables in Emacs.
4639 * Please do not remove this and leave it at the end of the file, where
4640 * Emacs will automagically detect them.
4641 * ---------------------------------------------------------------------
4644 * indent-tabs-mode: t
4648 * vim:noexpandtab:sw=4:ts=4: