1 /* src/vm/jit/alpha/codegen.c - machine code generator for Alpha
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: Joseph Wenninger
35 $Id: codegen.c 4530 2006-02-21 09:11:53Z twisti $
48 #include "vm/jit/alpha/arch.h"
49 #include "vm/jit/alpha/codegen.h"
51 #include "native/jni.h"
52 #include "native/native.h"
53 #include "vm/builtin.h"
54 #include "vm/exceptions.h"
55 #include "vm/global.h"
56 #include "vm/loader.h"
57 #include "vm/options.h"
58 #include "vm/stringlocal.h"
60 #include "vm/jit/asmpart.h"
61 #include "vm/jit/codegen-common.h"
62 #include "vm/jit/dseg.h"
63 #include "vm/jit/jit.h"
64 #include "vm/jit/parse.h"
65 #include "vm/jit/patcher.h"
66 #include "vm/jit/reg.h"
68 #if defined(ENABLE_LSRA)
69 # include "vm/jit/allocator/lsra.h"
73 /* codegen *********************************************************************
75 Generates machine code.
77 *******************************************************************************/
79 bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
81 s4 len, s1, s2, s3, d, disp;
90 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
91 builtintable_entry *bte;
94 /* prevent compiler warnings */
105 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
107 /* space to save used callee saved registers */
109 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
110 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
112 parentargs_base = rd->memuse + savedregs_num;
114 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
115 if (checksync && (m->flags & ACC_SYNCHRONIZED))
119 /* create method header */
121 (void) dseg_addaddress(cd, m); /* MethodPointer */
122 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
124 #if defined(USE_THREADS)
125 /* IsSync contains the offset relative to the stack pointer for the
126 argument of monitor_exit used in the exception handler. Since the
127 offset could be zero and give a wrong meaning of the flag it is
131 if (checksync && (m->flags & ACC_SYNCHRONIZED))
132 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
135 (void) dseg_adds4(cd, 0); /* IsSync */
137 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
138 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
139 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
141 dseg_addlinenumbertablesize(cd);
143 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
145 /* create exception table */
147 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
148 dseg_addtarget(cd, ex->start);
149 dseg_addtarget(cd, ex->end);
150 dseg_addtarget(cd, ex->handler);
151 (void) dseg_addaddress(cd, ex->catchtype.cls);
154 /* initialize mcode variables */
156 mcodeptr = (s4 *) cd->mcodeptr;
158 /* create stack frame (if necessary) */
161 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
163 /* save return address and used callee saved registers */
166 if (!m->isleafmethod) {
167 p--; M_AST(REG_RA, REG_SP, p * 8);
169 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
170 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
172 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
173 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
176 /* take arguments out of register or stack frame */
180 for (p = 0, l = 0; p < md->paramcount; p++) {
181 t = md->paramtypes[p].type;
182 var = &(rd->locals[l][t]);
184 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
188 s1 = md->params[p].regoff;
189 if (IS_INT_LNG_TYPE(t)) { /* integer args */
190 if (!md->params[p].inmemory) { /* register arguments */
191 s2 = rd->argintregs[s1];
192 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
193 M_INTMOVE(s2, var->regoff);
195 } else { /* reg arg -> spilled */
196 M_LST(s2, REG_SP, var->regoff * 8);
199 } else { /* stack arguments */
200 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
201 M_LLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
203 } else { /* stack arg -> spilled */
204 var->regoff = parentargs_base + s1;
208 } else { /* floating args */
209 if (!md->params[p].inmemory) { /* register arguments */
210 s2 = rd->argfltregs[s1];
211 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
212 M_FLTMOVE(s2, var->regoff);
214 } else { /* reg arg -> spilled */
215 M_DST(s2, REG_SP, var->regoff * 8);
218 } else { /* stack arguments */
219 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
220 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 8);
222 } else { /* stack-arg -> spilled */
223 var->regoff = parentargs_base + s1;
229 /* call monitorenter function */
231 #if defined(USE_THREADS)
232 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
233 /* stack offset for monitor argument */
238 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT + FLT_ARG_CNT) * 8);
240 for (p = 0; p < INT_ARG_CNT; p++)
241 M_LST(rd->argintregs[p], REG_SP, p * 8);
243 for (p = 0; p < FLT_ARG_CNT; p++)
244 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
246 s1 += INT_ARG_CNT + FLT_ARG_CNT;
249 /* decide which monitor enter function to call */
251 if (m->flags & ACC_STATIC) {
252 disp = dseg_addaddress(cd, m->class);
253 M_ALD(rd->argintregs[0], REG_PV, disp);
254 M_AST(rd->argintregs[0], REG_SP, s1 * 8);
255 disp = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
256 M_ALD(REG_PV, REG_PV, disp);
257 M_JSR(REG_RA, REG_PV);
258 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
259 M_LDA(REG_PV, REG_RA, disp);
262 M_BEQZ(rd->argintregs[0], 0);
263 codegen_addxnullrefs(cd, mcodeptr);
264 M_AST(rd->argintregs[0], REG_SP, s1 * 8);
265 disp = dseg_addaddress(cd, BUILTIN_monitorenter);
266 M_ALD(REG_PV, REG_PV, disp);
267 M_JSR(REG_RA, REG_PV);
268 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
269 M_LDA(REG_PV, REG_RA, disp);
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);
279 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
284 /* call trace function */
287 M_LDA(REG_SP, REG_SP, -((INT_ARG_CNT + FLT_ARG_CNT + 2) * 8));
288 M_AST(REG_RA, REG_SP, 1 * 8);
290 /* save integer argument registers */
292 for (p = 0; p < md->paramcount && p < INT_ARG_CNT; p++)
293 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
295 /* save and copy float arguments into integer registers */
297 for (p = 0; p < md->paramcount && p < FLT_ARG_CNT; p++) {
298 t = md->paramtypes[p].type;
300 if (IS_FLT_DBL_TYPE(t)) {
301 if (IS_2_WORD_TYPE(t)) {
302 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
305 M_FST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
308 M_LLD(rd->argintregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
311 M_DST(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
315 disp = dseg_addaddress(cd, m);
316 M_ALD(REG_ITMP1, REG_PV, disp);
317 M_AST(REG_ITMP1, REG_SP, 0 * 8);
318 disp = dseg_addaddress(cd, (void *) builtin_trace_args);
319 M_ALD(REG_PV, REG_PV, disp);
320 M_JSR(REG_RA, REG_PV);
321 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
322 M_LDA(REG_PV, REG_RA, disp);
323 M_ALD(REG_RA, REG_SP, 1 * 8);
325 /* restore integer argument registers */
327 for (p = 0; p < md->paramcount && p < INT_ARG_CNT; p++)
328 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
330 /* restore float argument registers */
332 for (p = 0; p < md->paramcount && p < FLT_ARG_CNT; p++) {
333 t = md->paramtypes[p].type;
335 if (IS_FLT_DBL_TYPE(t)) {
336 if (IS_2_WORD_TYPE(t)) {
337 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
340 M_FLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
344 M_DLD(rd->argfltregs[p], REG_SP, (2 + INT_ARG_CNT + p) * 8);
348 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT + 2) * 8);
353 /* end of header generation */
355 /* walk through all basic blocks */
357 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
359 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
361 if (bptr->flags >= BBREACHED) {
363 /* branch resolving */
367 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
368 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
369 brefs->branchpos, bptr->mpc);
373 /* copy interface registers to their destination */
378 #if defined(ENABLE_LSRA)
380 while (src != NULL) {
382 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
383 /* d = reg_of_var(m, src, REG_ITMP1); */
384 if (!(src->flags & INMEMORY))
388 M_INTMOVE(REG_ITMP1, d);
389 store_reg_to_var_int(src, d);
395 while (src != NULL) {
397 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
398 d = reg_of_var(rd, src, REG_ITMP1);
399 M_INTMOVE(REG_ITMP1, d);
400 store_reg_to_var_int(src, d);
402 d = reg_of_var(rd, src, REG_IFTMP);
403 if ((src->varkind != STACKVAR)) {
405 if (IS_FLT_DBL_TYPE(s2)) {
406 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
407 s1 = rd->interfaces[len][s2].regoff;
410 M_DLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
412 store_reg_to_var_flt(src, d);
415 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
416 s1 = rd->interfaces[len][s2].regoff;
419 M_LLD(d, REG_SP, rd->interfaces[len][s2].regoff * 8);
421 store_reg_to_var_int(src, d);
427 #if defined(ENABLE_LSRA)
431 /* walk through all instructions */
436 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
437 if (iptr->line != currentline) {
438 dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
439 currentline = iptr->line;
442 MCODECHECK(64); /* an instruction usually needs < 64 words */
445 case ICMD_INLINE_START:
446 case ICMD_INLINE_END:
449 case ICMD_NOP: /* ... ==> ... */
452 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
454 var_to_reg_int(s1, src, REG_ITMP1);
456 codegen_addxnullrefs(cd, mcodeptr);
459 /* constant operations ************************************************/
461 case ICMD_ICONST: /* ... ==> ..., constant */
462 /* op1 = 0, val.i = constant */
464 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
465 ICONST(d, iptr->val.i);
466 store_reg_to_var_int(iptr->dst, d);
469 case ICMD_LCONST: /* ... ==> ..., constant */
470 /* op1 = 0, val.l = constant */
472 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
473 LCONST(d, iptr->val.l);
474 store_reg_to_var_int(iptr->dst, d);
477 case ICMD_FCONST: /* ... ==> ..., constant */
478 /* op1 = 0, val.f = constant */
480 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
481 disp = dseg_addfloat(cd, iptr->val.f);
482 M_FLD(d, REG_PV, disp);
483 store_reg_to_var_flt(iptr->dst, d);
486 case ICMD_DCONST: /* ... ==> ..., constant */
487 /* op1 = 0, val.d = constant */
489 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
490 disp = dseg_adddouble(cd, iptr->val.d);
491 M_DLD(d, REG_PV, disp);
492 store_reg_to_var_flt(iptr->dst, d);
495 case ICMD_ACONST: /* ... ==> ..., constant */
496 /* op1 = 0, val.a = constant */
498 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
500 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
501 disp = dseg_addaddress(cd, iptr->val.a);
503 codegen_addpatchref(cd, mcodeptr,
505 (unresolved_class *) iptr->target, disp);
507 if (opt_showdisassemble)
510 M_ALD(d, REG_PV, disp);
513 if (iptr->val.a == NULL) {
514 M_INTMOVE(REG_ZERO, d);
516 disp = dseg_addaddress(cd, iptr->val.a);
517 M_ALD(d, REG_PV, disp);
520 store_reg_to_var_int(iptr->dst, d);
524 /* load/store operations **********************************************/
526 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
527 case ICMD_LLOAD: /* op1 = local variable */
530 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
531 if ((iptr->dst->varkind == LOCALVAR) &&
532 (iptr->dst->varnum == iptr->op1))
534 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
535 if (var->flags & INMEMORY) {
536 M_LLD(d, REG_SP, var->regoff * 8);
538 M_INTMOVE(var->regoff, d);
540 store_reg_to_var_int(iptr->dst, d);
543 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
544 case ICMD_DLOAD: /* op1 = local variable */
546 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
547 if ((iptr->dst->varkind == LOCALVAR) &&
548 (iptr->dst->varnum == iptr->op1))
550 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
551 if (var->flags & INMEMORY) {
552 M_DLD(d, REG_SP, var->regoff * 8);
554 M_FLTMOVE(var->regoff, d);
556 store_reg_to_var_flt(iptr->dst, d);
560 case ICMD_ISTORE: /* ..., value ==> ... */
561 case ICMD_LSTORE: /* op1 = local variable */
564 if ((src->varkind == LOCALVAR) &&
565 (src->varnum == iptr->op1))
567 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
568 if (var->flags & INMEMORY) {
569 var_to_reg_int(s1, src, REG_ITMP1);
570 M_LST(s1, REG_SP, var->regoff * 8);
572 var_to_reg_int(s1, src, var->regoff);
573 M_INTMOVE(s1, var->regoff);
577 case ICMD_FSTORE: /* ..., value ==> ... */
578 case ICMD_DSTORE: /* op1 = local variable */
580 if ((src->varkind == LOCALVAR) &&
581 (src->varnum == iptr->op1))
583 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
584 if (var->flags & INMEMORY) {
585 var_to_reg_flt(s1, src, REG_FTMP1);
586 M_DST(s1, REG_SP, var->regoff * 8);
588 var_to_reg_flt(s1, src, var->regoff);
589 M_FLTMOVE(s1, var->regoff);
594 /* pop/dup/swap operations ********************************************/
596 /* attention: double and longs are only one entry in CACAO ICMDs */
598 case ICMD_POP: /* ..., value ==> ... */
599 case ICMD_POP2: /* ..., value, value ==> ... */
602 case ICMD_DUP: /* ..., a ==> ..., a, a */
603 M_COPY(src, iptr->dst);
606 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
608 M_COPY(src, iptr->dst);
609 M_COPY(src->prev, iptr->dst->prev);
610 M_COPY(iptr->dst, iptr->dst->prev->prev);
613 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
615 M_COPY(src, iptr->dst);
616 M_COPY(src->prev, iptr->dst->prev);
617 M_COPY(src->prev->prev, iptr->dst->prev->prev);
618 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
621 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
623 M_COPY(src, iptr->dst);
624 M_COPY(src->prev, iptr->dst->prev);
627 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
629 M_COPY(src, iptr->dst);
630 M_COPY(src->prev, iptr->dst->prev);
631 M_COPY(src->prev->prev, iptr->dst->prev->prev);
632 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
633 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
636 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
638 M_COPY(src, iptr->dst);
639 M_COPY(src->prev, iptr->dst->prev);
640 M_COPY(src->prev->prev, iptr->dst->prev->prev);
641 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
642 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
643 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
646 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
648 M_COPY(src, iptr->dst->prev);
649 M_COPY(src->prev, iptr->dst);
653 /* integer operations *************************************************/
655 case ICMD_INEG: /* ..., value ==> ..., - value */
657 var_to_reg_int(s1, src, REG_ITMP1);
658 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
659 M_ISUB(REG_ZERO, s1, d);
660 store_reg_to_var_int(iptr->dst, d);
663 case ICMD_LNEG: /* ..., value ==> ..., - value */
665 var_to_reg_int(s1, src, REG_ITMP1);
666 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
667 M_LSUB(REG_ZERO, s1, d);
668 store_reg_to_var_int(iptr->dst, d);
671 case ICMD_I2L: /* ..., value ==> ..., value */
673 var_to_reg_int(s1, src, REG_ITMP1);
674 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
676 store_reg_to_var_int(iptr->dst, d);
679 case ICMD_L2I: /* ..., value ==> ..., value */
681 var_to_reg_int(s1, src, REG_ITMP1);
682 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
683 M_IADD(s1, REG_ZERO, d);
684 store_reg_to_var_int(iptr->dst, d);
687 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
689 var_to_reg_int(s1, src, REG_ITMP1);
690 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
691 if (has_ext_instr_set) {
694 M_SLL_IMM(s1, 56, d);
695 M_SRA_IMM( d, 56, d);
697 store_reg_to_var_int(iptr->dst, d);
700 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
702 var_to_reg_int(s1, src, REG_ITMP1);
703 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
705 store_reg_to_var_int(iptr->dst, d);
708 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
710 var_to_reg_int(s1, src, REG_ITMP1);
711 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
712 if (has_ext_instr_set) {
715 M_SLL_IMM(s1, 48, d);
716 M_SRA_IMM( d, 48, d);
718 store_reg_to_var_int(iptr->dst, d);
722 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
724 var_to_reg_int(s1, src->prev, REG_ITMP1);
725 var_to_reg_int(s2, src, REG_ITMP2);
726 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
728 store_reg_to_var_int(iptr->dst, d);
731 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
732 /* val.i = constant */
734 var_to_reg_int(s1, src, REG_ITMP1);
735 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
736 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
737 M_IADD_IMM(s1, iptr->val.i, d);
739 ICONST(REG_ITMP2, iptr->val.i);
740 M_IADD(s1, REG_ITMP2, d);
742 store_reg_to_var_int(iptr->dst, d);
745 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
747 var_to_reg_int(s1, src->prev, REG_ITMP1);
748 var_to_reg_int(s2, src, REG_ITMP2);
749 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
751 store_reg_to_var_int(iptr->dst, d);
754 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
755 /* val.l = constant */
757 var_to_reg_int(s1, src, REG_ITMP1);
758 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
759 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
760 M_LADD_IMM(s1, iptr->val.l, d);
762 LCONST(REG_ITMP2, iptr->val.l);
763 M_LADD(s1, REG_ITMP2, d);
765 store_reg_to_var_int(iptr->dst, d);
768 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
770 var_to_reg_int(s1, src->prev, REG_ITMP1);
771 var_to_reg_int(s2, src, REG_ITMP2);
772 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
774 store_reg_to_var_int(iptr->dst, d);
777 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
778 /* val.i = constant */
780 var_to_reg_int(s1, src, REG_ITMP1);
781 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
782 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
783 M_ISUB_IMM(s1, iptr->val.i, d);
785 ICONST(REG_ITMP2, iptr->val.i);
786 M_ISUB(s1, REG_ITMP2, d);
788 store_reg_to_var_int(iptr->dst, d);
791 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
793 var_to_reg_int(s1, src->prev, REG_ITMP1);
794 var_to_reg_int(s2, src, REG_ITMP2);
795 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
797 store_reg_to_var_int(iptr->dst, d);
800 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
801 /* val.l = constant */
803 var_to_reg_int(s1, src, REG_ITMP1);
804 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
805 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
806 M_LSUB_IMM(s1, iptr->val.l, d);
808 LCONST(REG_ITMP2, iptr->val.l);
809 M_LSUB(s1, REG_ITMP2, d);
811 store_reg_to_var_int(iptr->dst, d);
814 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
816 var_to_reg_int(s1, src->prev, REG_ITMP1);
817 var_to_reg_int(s2, src, REG_ITMP2);
818 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
820 store_reg_to_var_int(iptr->dst, d);
823 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
824 /* val.i = constant */
826 var_to_reg_int(s1, src, REG_ITMP1);
827 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
828 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
829 M_IMUL_IMM(s1, iptr->val.i, d);
831 ICONST(REG_ITMP2, iptr->val.i);
832 M_IMUL(s1, REG_ITMP2, d);
834 store_reg_to_var_int(iptr->dst, d);
837 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
839 var_to_reg_int(s1, src->prev, REG_ITMP1);
840 var_to_reg_int(s2, src, REG_ITMP2);
841 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
843 store_reg_to_var_int(iptr->dst, d);
846 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
847 /* val.l = constant */
849 var_to_reg_int(s1, src, REG_ITMP1);
850 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
851 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
852 M_LMUL_IMM(s1, iptr->val.l, d);
854 LCONST(REG_ITMP2, iptr->val.l);
855 M_LMUL(s1, REG_ITMP2, d);
857 store_reg_to_var_int(iptr->dst, d);
860 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
861 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
863 var_to_reg_int(s1, src->prev, REG_ITMP1);
864 var_to_reg_int(s2, src, REG_ITMP2);
865 d = reg_of_var(rd, iptr->dst, REG_RESULT);
867 codegen_addxdivrefs(cd, mcodeptr);
869 M_MOV(s1, rd->argintregs[0]);
870 M_MOV(s2, rd->argintregs[1]);
872 disp = dseg_addaddress(cd, bte->fp);
873 M_ALD(REG_PV, REG_PV, disp);
874 M_JSR(REG_RA, REG_PV);
875 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
876 M_LDA(REG_PV, REG_RA, -disp);
878 M_IADD(REG_RESULT, REG_ZERO, d); /* sign extend (bugfix for gcc -O2) */
879 store_reg_to_var_int(iptr->dst, d);
882 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
883 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
885 var_to_reg_int(s1, src->prev, REG_ITMP1);
886 var_to_reg_int(s2, src, REG_ITMP2);
887 d = reg_of_var(rd, iptr->dst, REG_RESULT);
889 codegen_addxdivrefs(cd, mcodeptr);
891 M_MOV(s1, rd->argintregs[0]);
892 M_MOV(s2, rd->argintregs[1]);
894 disp = dseg_addaddress(cd, bte->fp);
895 M_ALD(REG_PV, REG_PV, disp);
896 M_JSR(REG_RA, REG_PV);
897 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
898 M_LDA(REG_PV, REG_RA, -disp);
900 M_INTMOVE(REG_RESULT, d);
901 store_reg_to_var_int(iptr->dst, d);
904 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
905 case ICMD_LDIVPOW2: /* val.i = constant */
907 var_to_reg_int(s1, src, REG_ITMP1);
908 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
909 if (iptr->val.i <= 15) {
910 M_LDA(REG_ITMP2, s1, (1 << iptr->val.i) -1);
911 M_CMOVGE(s1, s1, REG_ITMP2);
913 M_SRA_IMM(s1, 63, REG_ITMP2);
914 M_SRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
915 M_LADD(s1, REG_ITMP2, REG_ITMP2);
917 M_SRA_IMM(REG_ITMP2, iptr->val.i, d);
918 store_reg_to_var_int(iptr->dst, d);
921 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
923 var_to_reg_int(s1, src->prev, REG_ITMP1);
924 var_to_reg_int(s2, src, REG_ITMP2);
925 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
926 M_AND_IMM(s2, 0x1f, REG_ITMP3);
927 M_SLL(s1, REG_ITMP3, d);
928 M_IADD(d, REG_ZERO, d);
929 store_reg_to_var_int(iptr->dst, d);
932 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
933 /* val.i = constant */
935 var_to_reg_int(s1, src, REG_ITMP1);
936 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
937 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
938 M_IADD(d, REG_ZERO, d);
939 store_reg_to_var_int(iptr->dst, d);
942 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
944 var_to_reg_int(s1, src->prev, REG_ITMP1);
945 var_to_reg_int(s2, src, REG_ITMP2);
946 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
947 M_AND_IMM(s2, 0x1f, REG_ITMP3);
948 M_SRA(s1, REG_ITMP3, d);
949 store_reg_to_var_int(iptr->dst, d);
952 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
953 /* val.i = constant */
955 var_to_reg_int(s1, src, REG_ITMP1);
956 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
957 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
958 store_reg_to_var_int(iptr->dst, d);
961 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
963 var_to_reg_int(s1, src->prev, REG_ITMP1);
964 var_to_reg_int(s2, src, REG_ITMP2);
965 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
966 M_AND_IMM(s2, 0x1f, REG_ITMP2);
968 M_SRL(d, REG_ITMP2, d);
969 M_IADD(d, REG_ZERO, d);
970 store_reg_to_var_int(iptr->dst, d);
973 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
974 /* val.i = constant */
976 var_to_reg_int(s1, src, REG_ITMP1);
977 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
979 M_SRL_IMM(d, iptr->val.i & 0x1f, d);
980 M_IADD(d, REG_ZERO, d);
981 store_reg_to_var_int(iptr->dst, d);
984 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
986 var_to_reg_int(s1, src->prev, REG_ITMP1);
987 var_to_reg_int(s2, src, REG_ITMP2);
988 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
990 store_reg_to_var_int(iptr->dst, d);
993 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
994 /* val.i = constant */
996 var_to_reg_int(s1, src, REG_ITMP1);
997 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
998 M_SLL_IMM(s1, iptr->val.i & 0x3f, d);
999 store_reg_to_var_int(iptr->dst, d);
1002 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1004 var_to_reg_int(s1, src->prev, REG_ITMP1);
1005 var_to_reg_int(s2, src, REG_ITMP2);
1006 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1008 store_reg_to_var_int(iptr->dst, d);
1011 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1012 /* val.i = constant */
1014 var_to_reg_int(s1, src, REG_ITMP1);
1015 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1016 M_SRA_IMM(s1, iptr->val.i & 0x3f, d);
1017 store_reg_to_var_int(iptr->dst, d);
1020 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1022 var_to_reg_int(s1, src->prev, REG_ITMP1);
1023 var_to_reg_int(s2, src, REG_ITMP2);
1024 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1026 store_reg_to_var_int(iptr->dst, d);
1029 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1030 /* val.i = constant */
1032 var_to_reg_int(s1, src, REG_ITMP1);
1033 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1034 M_SRL_IMM(s1, iptr->val.i & 0x3f, d);
1035 store_reg_to_var_int(iptr->dst, d);
1038 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1041 var_to_reg_int(s1, src->prev, REG_ITMP1);
1042 var_to_reg_int(s2, src, REG_ITMP2);
1043 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1045 store_reg_to_var_int(iptr->dst, d);
1048 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1049 /* val.i = constant */
1051 var_to_reg_int(s1, src, REG_ITMP1);
1052 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1053 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1054 M_AND_IMM(s1, iptr->val.i, d);
1055 } else if (iptr->val.i == 0xffff) {
1057 } else if (iptr->val.i == 0xffffff) {
1058 M_ZAPNOT_IMM(s1, 0x07, d);
1060 ICONST(REG_ITMP2, iptr->val.i);
1061 M_AND(s1, REG_ITMP2, d);
1063 store_reg_to_var_int(iptr->dst, d);
1066 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1067 /* val.i = constant */
1069 var_to_reg_int(s1, src, REG_ITMP1);
1070 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1072 M_MOV(s1, REG_ITMP1);
1075 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1076 M_AND_IMM(s1, iptr->val.i, d);
1078 M_ISUB(REG_ZERO, s1, d);
1079 M_AND_IMM(d, iptr->val.i, d);
1080 } else if (iptr->val.i == 0xffff) {
1083 M_ISUB(REG_ZERO, s1, d);
1085 } else if (iptr->val.i == 0xffffff) {
1086 M_ZAPNOT_IMM(s1, 0x07, d);
1088 M_ISUB(REG_ZERO, s1, d);
1089 M_ZAPNOT_IMM(d, 0x07, d);
1091 ICONST(REG_ITMP2, iptr->val.i);
1092 M_AND(s1, REG_ITMP2, d);
1094 M_ISUB(REG_ZERO, s1, d);
1095 M_AND(d, REG_ITMP2, d);
1097 M_ISUB(REG_ZERO, d, d);
1098 store_reg_to_var_int(iptr->dst, d);
1101 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1102 /* val.l = constant */
1104 var_to_reg_int(s1, src, REG_ITMP1);
1105 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1106 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1107 M_AND_IMM(s1, iptr->val.l, d);
1108 } else if (iptr->val.l == 0xffffL) {
1110 } else if (iptr->val.l == 0xffffffL) {
1111 M_ZAPNOT_IMM(s1, 0x07, d);
1112 } else if (iptr->val.l == 0xffffffffL) {
1114 } else if (iptr->val.l == 0xffffffffffL) {
1115 M_ZAPNOT_IMM(s1, 0x1f, d);
1116 } else if (iptr->val.l == 0xffffffffffffL) {
1117 M_ZAPNOT_IMM(s1, 0x3f, d);
1118 } else if (iptr->val.l == 0xffffffffffffffL) {
1119 M_ZAPNOT_IMM(s1, 0x7f, d);
1121 LCONST(REG_ITMP2, iptr->val.l);
1122 M_AND(s1, REG_ITMP2, d);
1124 store_reg_to_var_int(iptr->dst, d);
1127 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1128 /* val.l = constant */
1130 var_to_reg_int(s1, src, REG_ITMP1);
1131 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1133 M_MOV(s1, REG_ITMP1);
1136 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1137 M_AND_IMM(s1, iptr->val.l, d);
1139 M_LSUB(REG_ZERO, s1, d);
1140 M_AND_IMM(d, iptr->val.l, d);
1141 } else if (iptr->val.l == 0xffffL) {
1144 M_LSUB(REG_ZERO, s1, d);
1146 } else if (iptr->val.l == 0xffffffL) {
1147 M_ZAPNOT_IMM(s1, 0x07, d);
1149 M_LSUB(REG_ZERO, s1, d);
1150 M_ZAPNOT_IMM(d, 0x07, d);
1151 } else if (iptr->val.l == 0xffffffffL) {
1154 M_LSUB(REG_ZERO, s1, d);
1156 } else if (iptr->val.l == 0xffffffffffL) {
1157 M_ZAPNOT_IMM(s1, 0x1f, d);
1159 M_LSUB(REG_ZERO, s1, d);
1160 M_ZAPNOT_IMM(d, 0x1f, d);
1161 } else if (iptr->val.l == 0xffffffffffffL) {
1162 M_ZAPNOT_IMM(s1, 0x3f, d);
1164 M_LSUB(REG_ZERO, s1, d);
1165 M_ZAPNOT_IMM(d, 0x3f, d);
1166 } else if (iptr->val.l == 0xffffffffffffffL) {
1167 M_ZAPNOT_IMM(s1, 0x7f, d);
1169 M_LSUB(REG_ZERO, s1, d);
1170 M_ZAPNOT_IMM(d, 0x7f, d);
1172 LCONST(REG_ITMP2, iptr->val.l);
1173 M_AND(s1, REG_ITMP2, d);
1175 M_LSUB(REG_ZERO, s1, d);
1176 M_AND(d, REG_ITMP2, d);
1178 M_LSUB(REG_ZERO, d, d);
1179 store_reg_to_var_int(iptr->dst, d);
1182 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1185 var_to_reg_int(s1, src->prev, REG_ITMP1);
1186 var_to_reg_int(s2, src, REG_ITMP2);
1187 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1189 store_reg_to_var_int(iptr->dst, d);
1192 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1193 /* val.i = constant */
1195 var_to_reg_int(s1, src, REG_ITMP1);
1196 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1197 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1198 M_OR_IMM(s1, iptr->val.i, d);
1200 ICONST(REG_ITMP2, iptr->val.i);
1201 M_OR(s1, REG_ITMP2, d);
1203 store_reg_to_var_int(iptr->dst, d);
1206 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1207 /* val.l = constant */
1209 var_to_reg_int(s1, src, REG_ITMP1);
1210 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1211 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1212 M_OR_IMM(s1, iptr->val.l, d);
1214 LCONST(REG_ITMP2, iptr->val.l);
1215 M_OR(s1, REG_ITMP2, d);
1217 store_reg_to_var_int(iptr->dst, d);
1220 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1223 var_to_reg_int(s1, src->prev, REG_ITMP1);
1224 var_to_reg_int(s2, src, REG_ITMP2);
1225 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1227 store_reg_to_var_int(iptr->dst, d);
1230 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1231 /* val.i = constant */
1233 var_to_reg_int(s1, src, REG_ITMP1);
1234 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1235 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1236 M_XOR_IMM(s1, iptr->val.i, d);
1238 ICONST(REG_ITMP2, iptr->val.i);
1239 M_XOR(s1, REG_ITMP2, d);
1241 store_reg_to_var_int(iptr->dst, d);
1244 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1245 /* val.l = constant */
1247 var_to_reg_int(s1, src, REG_ITMP1);
1248 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1249 if ((iptr->val.l >= 0) && (iptr->val.l <= 255)) {
1250 M_XOR_IMM(s1, iptr->val.l, d);
1252 LCONST(REG_ITMP2, iptr->val.l);
1253 M_XOR(s1, REG_ITMP2, d);
1255 store_reg_to_var_int(iptr->dst, d);
1259 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1261 var_to_reg_int(s1, src->prev, REG_ITMP1);
1262 var_to_reg_int(s2, src, REG_ITMP2);
1263 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1264 M_CMPLT(s1, s2, REG_ITMP3);
1265 M_CMPLT(s2, s1, REG_ITMP1);
1266 M_LSUB(REG_ITMP1, REG_ITMP3, d);
1267 store_reg_to_var_int(iptr->dst, d);
1271 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1272 /* op1 = variable, val.i = constant */
1274 var = &(rd->locals[iptr->op1][TYPE_INT]);
1275 if (var->flags & INMEMORY) {
1277 M_LLD(s1, REG_SP, var->regoff * 8);
1280 if ((iptr->val.i >= 0) && (iptr->val.i <= 255)) {
1281 M_IADD_IMM(s1, iptr->val.i, s1);
1282 } else if ((iptr->val.i > -256) && (iptr->val.i < 0)) {
1283 M_ISUB_IMM(s1, (-iptr->val.i), s1);
1285 M_LDA (s1, s1, iptr->val.i);
1286 M_IADD(s1, REG_ZERO, s1);
1288 if (var->flags & INMEMORY)
1289 M_LST(s1, REG_SP, var->regoff * 8);
1293 /* floating operations ************************************************/
1295 case ICMD_FNEG: /* ..., value ==> ..., - value */
1297 var_to_reg_flt(s1, src, REG_FTMP1);
1298 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1300 store_reg_to_var_flt(iptr->dst, d);
1303 case ICMD_DNEG: /* ..., value ==> ..., - value */
1305 var_to_reg_flt(s1, src, REG_FTMP1);
1306 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1308 store_reg_to_var_flt(iptr->dst, d);
1311 case ICMD_FADD: /* ..., 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_FTMP3);
1319 if (d == s1 || d == s2) {
1320 M_FADDS(s1, s2, REG_FTMP3);
1322 M_FMOV(REG_FTMP3, d);
1328 store_reg_to_var_flt(iptr->dst, d);
1331 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1333 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1334 var_to_reg_flt(s2, src, REG_FTMP2);
1335 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1339 if (d == s1 || d == s2) {
1340 M_DADDS(s1, s2, REG_FTMP3);
1342 M_FMOV(REG_FTMP3, d);
1348 store_reg_to_var_flt(iptr->dst, d);
1351 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1353 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1354 var_to_reg_flt(s2, src, REG_FTMP2);
1355 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1359 if (d == s1 || d == s2) {
1360 M_FSUBS(s1, s2, REG_FTMP3);
1362 M_FMOV(REG_FTMP3, d);
1368 store_reg_to_var_flt(iptr->dst, d);
1371 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1373 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1374 var_to_reg_flt(s2, src, REG_FTMP2);
1375 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1379 if (d == s1 || d == s2) {
1380 M_DSUBS(s1, s2, REG_FTMP3);
1382 M_FMOV(REG_FTMP3, d);
1388 store_reg_to_var_flt(iptr->dst, d);
1391 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1393 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1394 var_to_reg_flt(s2, src, REG_FTMP2);
1395 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1399 if (d == s1 || d == s2) {
1400 M_FMULS(s1, s2, REG_FTMP3);
1402 M_FMOV(REG_FTMP3, d);
1408 store_reg_to_var_flt(iptr->dst, d);
1411 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1413 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1414 var_to_reg_flt(s2, src, REG_FTMP2);
1415 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1419 if (d == s1 || d == s2) {
1420 M_DMULS(s1, s2, REG_FTMP3);
1422 M_FMOV(REG_FTMP3, d);
1428 store_reg_to_var_flt(iptr->dst, d);
1431 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1433 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1434 var_to_reg_flt(s2, src, REG_FTMP2);
1435 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1439 if (d == s1 || d == s2) {
1440 M_FDIVS(s1, s2, REG_FTMP3);
1442 M_FMOV(REG_FTMP3, d);
1448 store_reg_to_var_flt(iptr->dst, d);
1451 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1453 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1454 var_to_reg_flt(s2, src, REG_FTMP2);
1455 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1459 if (d == s1 || d == s2) {
1460 M_DDIVS(s1, s2, REG_FTMP3);
1462 M_FMOV(REG_FTMP3, d);
1468 store_reg_to_var_flt(iptr->dst, d);
1471 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1473 var_to_reg_int(s1, src, REG_ITMP1);
1474 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1475 disp = dseg_adddouble(cd, 0.0);
1476 M_LST(s1, REG_PV, disp);
1477 M_DLD(d, REG_PV, disp);
1479 store_reg_to_var_flt(iptr->dst, d);
1482 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1484 var_to_reg_int(s1, src, REG_ITMP1);
1485 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1486 disp = dseg_adddouble(cd, 0.0);
1487 M_LST(s1, REG_PV, disp);
1488 M_DLD(d, REG_PV, disp);
1490 store_reg_to_var_flt(iptr->dst, d);
1493 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1495 var_to_reg_flt(s1, src, REG_FTMP1);
1496 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1497 disp = dseg_adddouble(cd, 0.0);
1498 M_CVTDL_C(s1, REG_FTMP2);
1499 M_CVTLI(REG_FTMP2, REG_FTMP3);
1500 M_DST(REG_FTMP3, REG_PV, disp);
1501 M_ILD(d, REG_PV, disp);
1502 store_reg_to_var_int(iptr->dst, d);
1505 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1507 var_to_reg_flt(s1, src, REG_FTMP1);
1508 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1509 disp = dseg_adddouble(cd, 0.0);
1510 M_CVTDL_C(s1, REG_FTMP2);
1511 M_DST(REG_FTMP2, REG_PV, disp);
1512 M_LLD(d, REG_PV, disp);
1513 store_reg_to_var_int(iptr->dst, d);
1516 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1518 var_to_reg_flt(s1, src, REG_FTMP1);
1519 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1522 store_reg_to_var_flt(iptr->dst, d);
1525 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1527 var_to_reg_flt(s1, src, REG_FTMP1);
1528 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1535 store_reg_to_var_flt(iptr->dst, d);
1538 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1540 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1541 var_to_reg_flt(s2, src, REG_FTMP2);
1542 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1544 M_LSUB_IMM(REG_ZERO, 1, d);
1545 M_FCMPEQ(s1, s2, REG_FTMP3);
1546 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1548 M_FCMPLT(s2, s1, REG_FTMP3);
1549 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1550 M_LADD_IMM(REG_ZERO, 1, d);
1552 M_LSUB_IMM(REG_ZERO, 1, d);
1553 M_FCMPEQS(s1, s2, REG_FTMP3);
1555 M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
1557 M_FCMPLTS(s2, s1, REG_FTMP3);
1559 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1560 M_LADD_IMM(REG_ZERO, 1, d);
1562 store_reg_to_var_int(iptr->dst, d);
1565 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1567 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1568 var_to_reg_flt(s2, src, REG_FTMP2);
1569 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1571 M_LADD_IMM(REG_ZERO, 1, d);
1572 M_FCMPEQ(s1, s2, REG_FTMP3);
1573 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1575 M_FCMPLT(s1, s2, REG_FTMP3);
1576 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1577 M_LSUB_IMM(REG_ZERO, 1, d);
1579 M_LADD_IMM(REG_ZERO, 1, d);
1580 M_FCMPEQS(s1, s2, REG_FTMP3);
1582 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1584 M_FCMPLTS(s1, s2, REG_FTMP3);
1586 M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
1587 M_LSUB_IMM(REG_ZERO, 1, d);
1589 store_reg_to_var_int(iptr->dst, d);
1593 /* memory operations **************************************************/
1595 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1597 var_to_reg_int(s1, src, REG_ITMP1);
1598 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1599 gen_nullptr_check(s1);
1600 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1601 store_reg_to_var_int(iptr->dst, d);
1604 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1606 var_to_reg_int(s1, src->prev, REG_ITMP1);
1607 var_to_reg_int(s2, src, REG_ITMP2);
1608 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1609 if (iptr->op1 == 0) {
1610 gen_nullptr_check(s1);
1613 if (has_ext_instr_set) {
1614 M_LADD (s2, s1, REG_ITMP1);
1615 M_BLDU (d, REG_ITMP1, OFFSET (java_bytearray, data[0]));
1618 M_LADD(s2, s1, REG_ITMP1);
1619 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1620 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0])+1);
1621 M_EXTQH(REG_ITMP2, REG_ITMP1, d);
1622 M_SRA_IMM(d, 56, d);
1624 store_reg_to_var_int(iptr->dst, d);
1627 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1629 var_to_reg_int(s1, src->prev, REG_ITMP1);
1630 var_to_reg_int(s2, src, REG_ITMP2);
1631 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1632 if (iptr->op1 == 0) {
1633 gen_nullptr_check(s1);
1636 if (has_ext_instr_set) {
1637 M_LADD(s2, s1, REG_ITMP1);
1638 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1639 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1641 M_LADD (s2, s1, REG_ITMP1);
1642 M_LADD (s2, REG_ITMP1, REG_ITMP1);
1643 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
1644 M_LDA (REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
1645 M_EXTWL(REG_ITMP2, REG_ITMP1, d);
1647 store_reg_to_var_int(iptr->dst, d);
1650 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1652 var_to_reg_int(s1, src->prev, REG_ITMP1);
1653 var_to_reg_int(s2, src, REG_ITMP2);
1654 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1655 if (iptr->op1 == 0) {
1656 gen_nullptr_check(s1);
1659 if (has_ext_instr_set) {
1660 M_LADD(s2, s1, REG_ITMP1);
1661 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1662 M_SLDU( d, REG_ITMP1, OFFSET (java_shortarray, data[0]));
1665 M_LADD(s2, s1, REG_ITMP1);
1666 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1667 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
1668 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0])+2);
1669 M_EXTQH(REG_ITMP2, REG_ITMP1, d);
1670 M_SRA_IMM(d, 48, d);
1672 store_reg_to_var_int(iptr->dst, d);
1675 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1677 var_to_reg_int(s1, src->prev, REG_ITMP1);
1678 var_to_reg_int(s2, src, REG_ITMP2);
1679 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1680 if (iptr->op1 == 0) {
1681 gen_nullptr_check(s1);
1684 M_S4ADDQ(s2, s1, REG_ITMP1);
1685 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1686 store_reg_to_var_int(iptr->dst, d);
1689 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1691 var_to_reg_int(s1, src->prev, REG_ITMP1);
1692 var_to_reg_int(s2, src, REG_ITMP2);
1693 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1694 if (iptr->op1 == 0) {
1695 gen_nullptr_check(s1);
1698 M_S8ADDQ(s2, s1, REG_ITMP1);
1699 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1700 store_reg_to_var_int(iptr->dst, d);
1703 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1705 var_to_reg_int(s1, src->prev, REG_ITMP1);
1706 var_to_reg_int(s2, src, REG_ITMP2);
1707 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1708 if (iptr->op1 == 0) {
1709 gen_nullptr_check(s1);
1712 M_S4ADDQ(s2, s1, REG_ITMP1);
1713 M_FLD(d, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1714 store_reg_to_var_flt(iptr->dst, d);
1717 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1719 var_to_reg_int(s1, src->prev, REG_ITMP1);
1720 var_to_reg_int(s2, src, REG_ITMP2);
1721 d = reg_of_var(rd, iptr->dst, REG_FTMP2);
1722 if (iptr->op1 == 0) {
1723 gen_nullptr_check(s1);
1726 M_S8ADDQ(s2, s1, REG_ITMP1);
1727 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1728 store_reg_to_var_flt(iptr->dst, d);
1731 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1733 var_to_reg_int(s1, src->prev, REG_ITMP1);
1734 var_to_reg_int(s2, src, REG_ITMP2);
1735 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1736 if (iptr->op1 == 0) {
1737 gen_nullptr_check(s1);
1740 M_SAADDQ(s2, s1, REG_ITMP1);
1741 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1742 store_reg_to_var_int(iptr->dst, d);
1746 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1748 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1749 var_to_reg_int(s2, src->prev, REG_ITMP2);
1750 if (iptr->op1 == 0) {
1751 gen_nullptr_check(s1);
1754 var_to_reg_int(s3, src, REG_ITMP3);
1755 if (has_ext_instr_set) {
1756 M_LADD(s2, s1, REG_ITMP1);
1757 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1759 M_LADD(s2, s1, REG_ITMP1);
1760 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1761 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1762 M_INSBL(s3, REG_ITMP1, REG_ITMP3);
1763 M_MSKBL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
1764 M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP2);
1765 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
1769 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1771 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1772 var_to_reg_int(s2, src->prev, REG_ITMP2);
1773 if (iptr->op1 == 0) {
1774 gen_nullptr_check(s1);
1777 var_to_reg_int(s3, src, REG_ITMP3);
1778 if (has_ext_instr_set) {
1779 M_LADD(s2, s1, REG_ITMP1);
1780 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1781 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1783 M_LADD(s2, s1, REG_ITMP1);
1784 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1785 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
1786 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
1787 M_INSWL(s3, REG_ITMP1, REG_ITMP3);
1788 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
1789 M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP2);
1790 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
1794 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1796 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1797 var_to_reg_int(s2, src->prev, REG_ITMP2);
1798 if (iptr->op1 == 0) {
1799 gen_nullptr_check(s1);
1802 var_to_reg_int(s3, src, REG_ITMP3);
1803 if (has_ext_instr_set) {
1804 M_LADD(s2, s1, REG_ITMP1);
1805 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1806 M_SST(s3, REG_ITMP1, OFFSET(java_shortarray, data[0]));
1808 M_LADD(s2, s1, REG_ITMP1);
1809 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1810 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
1811 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
1812 M_INSWL(s3, REG_ITMP1, REG_ITMP3);
1813 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
1814 M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP2);
1815 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
1819 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1821 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1822 var_to_reg_int(s2, src->prev, REG_ITMP2);
1823 if (iptr->op1 == 0) {
1824 gen_nullptr_check(s1);
1827 var_to_reg_int(s3, src, REG_ITMP3);
1828 M_S4ADDQ(s2, s1, REG_ITMP1);
1829 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1832 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1834 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1835 var_to_reg_int(s2, src->prev, REG_ITMP2);
1836 if (iptr->op1 == 0) {
1837 gen_nullptr_check(s1);
1840 var_to_reg_int(s3, src, REG_ITMP3);
1841 M_S8ADDQ(s2, s1, REG_ITMP1);
1842 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1845 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1847 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1848 var_to_reg_int(s2, src->prev, REG_ITMP2);
1849 if (iptr->op1 == 0) {
1850 gen_nullptr_check(s1);
1853 var_to_reg_flt(s3, src, REG_FTMP3);
1854 M_S4ADDQ(s2, s1, REG_ITMP1);
1855 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1858 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1860 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1861 var_to_reg_int(s2, src->prev, REG_ITMP2);
1862 if (iptr->op1 == 0) {
1863 gen_nullptr_check(s1);
1866 var_to_reg_flt(s3, src, REG_FTMP3);
1867 M_S8ADDQ(s2, s1, REG_ITMP1);
1868 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1871 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1873 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1874 var_to_reg_int(s2, src->prev, REG_ITMP2);
1875 if (iptr->op1 == 0) {
1876 gen_nullptr_check(s1);
1879 var_to_reg_int(s3, src, REG_ITMP3);
1881 M_MOV(s1, rd->argintregs[0]);
1882 M_MOV(s3, rd->argintregs[1]);
1883 disp = dseg_addaddress(cd, BUILTIN_canstore);
1884 M_ALD(REG_PV, REG_PV, disp);
1885 M_JSR(REG_RA, REG_PV);
1886 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1887 M_LDA(REG_PV, REG_RA, -disp);
1889 M_BEQZ(REG_RESULT, 0);
1890 codegen_addxstorerefs(cd, mcodeptr);
1892 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1893 var_to_reg_int(s2, src->prev, REG_ITMP2);
1894 var_to_reg_int(s3, src, REG_ITMP3);
1895 M_SAADDQ(s2, s1, REG_ITMP1);
1896 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1900 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1902 var_to_reg_int(s1, src->prev, REG_ITMP1);
1903 var_to_reg_int(s2, src, REG_ITMP2);
1904 if (iptr->op1 == 0) {
1905 gen_nullptr_check(s1);
1908 M_S4ADDQ(s2, s1, REG_ITMP1);
1909 M_IST(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1912 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1914 var_to_reg_int(s1, src->prev, REG_ITMP1);
1915 var_to_reg_int(s2, src, REG_ITMP2);
1916 if (iptr->op1 == 0) {
1917 gen_nullptr_check(s1);
1920 M_S8ADDQ(s2, s1, REG_ITMP1);
1921 M_LST(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1924 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1926 var_to_reg_int(s1, src->prev, REG_ITMP1);
1927 var_to_reg_int(s2, src, REG_ITMP2);
1928 if (iptr->op1 == 0) {
1929 gen_nullptr_check(s1);
1932 M_SAADDQ(s2, s1, REG_ITMP1);
1933 M_AST(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1936 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1938 var_to_reg_int(s1, src->prev, REG_ITMP1);
1939 var_to_reg_int(s2, src, REG_ITMP2);
1940 if (iptr->op1 == 0) {
1941 gen_nullptr_check(s1);
1944 if (has_ext_instr_set) {
1945 M_LADD(s2, s1, REG_ITMP1);
1946 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1949 M_LADD(s2, s1, REG_ITMP1);
1950 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1951 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1952 M_INSBL(REG_ZERO, REG_ITMP1, REG_ITMP3);
1953 M_MSKBL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
1954 M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP2);
1955 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
1959 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1961 var_to_reg_int(s1, src->prev, REG_ITMP1);
1962 var_to_reg_int(s2, src, REG_ITMP2);
1963 if (iptr->op1 == 0) {
1964 gen_nullptr_check(s1);
1967 if (has_ext_instr_set) {
1968 M_LADD(s2, s1, REG_ITMP1);
1969 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1970 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
1973 M_LADD(s2, s1, REG_ITMP1);
1974 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1975 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_chararray, data[0]));
1976 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_chararray, data[0]));
1977 M_INSWL(REG_ZERO, REG_ITMP1, REG_ITMP3);
1978 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
1979 M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP2);
1980 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
1984 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1986 var_to_reg_int(s1, src->prev, REG_ITMP1);
1987 var_to_reg_int(s2, src, REG_ITMP2);
1988 if (iptr->op1 == 0) {
1989 gen_nullptr_check(s1);
1992 if (has_ext_instr_set) {
1993 M_LADD(s2, s1, REG_ITMP1);
1994 M_LADD(s2, REG_ITMP1, REG_ITMP1);
1995 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_shortarray, data[0]));
1998 M_LADD(s2, s1, REG_ITMP1);
1999 M_LADD(s2, REG_ITMP1, REG_ITMP1);
2000 M_LLD_U(REG_ITMP2, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2001 M_LDA(REG_ITMP1, REG_ITMP1, OFFSET(java_shortarray, data[0]));
2002 M_INSWL(REG_ZERO, REG_ITMP1, REG_ITMP3);
2003 M_MSKWL(REG_ITMP2, REG_ITMP1, REG_ITMP2);
2004 M_OR(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2005 M_LST_U(REG_ITMP2, REG_ITMP1, 0);
2010 case ICMD_GETSTATIC: /* ... ==> ..., value */
2011 /* op1 = type, val.a = field address */
2013 if (iptr->val.a == NULL) {
2014 disp = dseg_addaddress(cd, 0);
2016 codegen_addpatchref(cd, mcodeptr,
2017 PATCHER_get_putstatic,
2018 (unresolved_field *) iptr->target, disp);
2020 if (opt_showdisassemble)
2025 fieldinfo *fi = iptr->val.a;
2027 disp = dseg_addaddress(cd, &(fi->value));
2029 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2030 codegen_addpatchref(cd, mcodeptr,
2031 PATCHER_clinit, fi->class, 0);
2033 if (opt_showdisassemble)
2038 M_ALD(REG_ITMP1, REG_PV, disp);
2039 switch (iptr->op1) {
2041 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2042 M_ILD(d, REG_ITMP1, 0);
2043 store_reg_to_var_int(iptr->dst, d);
2046 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2047 M_LLD(d, REG_ITMP1, 0);
2048 store_reg_to_var_int(iptr->dst, d);
2051 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2052 M_ALD(d, REG_ITMP1, 0);
2053 store_reg_to_var_int(iptr->dst, d);
2056 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2057 M_FLD(d, REG_ITMP1, 0);
2058 store_reg_to_var_flt(iptr->dst, d);
2061 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2062 M_DLD(d, REG_ITMP1, 0);
2063 store_reg_to_var_flt(iptr->dst, d);
2068 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2069 /* op1 = type, val.a = field address */
2071 if (iptr->val.a == NULL) {
2072 disp = dseg_addaddress(cd, 0);
2074 codegen_addpatchref(cd, mcodeptr,
2075 PATCHER_get_putstatic,
2076 (unresolved_field *) iptr->target, disp);
2078 if (opt_showdisassemble)
2082 fieldinfo *fi = iptr->val.a;
2084 disp = dseg_addaddress(cd, &(fi->value));
2086 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2087 codegen_addpatchref(cd, mcodeptr,
2088 PATCHER_clinit, fi->class, 0);
2090 if (opt_showdisassemble)
2095 M_ALD(REG_ITMP1, REG_PV, disp);
2096 switch (iptr->op1) {
2098 var_to_reg_int(s2, src, REG_ITMP2);
2099 M_IST(s2, REG_ITMP1, 0);
2102 var_to_reg_int(s2, src, REG_ITMP2);
2103 M_LST(s2, REG_ITMP1, 0);
2106 var_to_reg_int(s2, src, REG_ITMP2);
2107 M_AST(s2, REG_ITMP1, 0);
2110 var_to_reg_flt(s2, src, REG_FTMP2);
2111 M_FST(s2, REG_ITMP1, 0);
2114 var_to_reg_flt(s2, src, REG_FTMP2);
2115 M_DST(s2, REG_ITMP1, 0);
2120 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2121 /* val = value (in current instruction) */
2122 /* op1 = type, val.a = field address (in */
2123 /* following NOP) */
2125 if (iptr[1].val.a == NULL) {
2126 disp = dseg_addaddress(cd, 0);
2128 codegen_addpatchref(cd, mcodeptr,
2129 PATCHER_get_putstatic,
2130 (unresolved_field *) iptr[1].target, disp);
2132 if (opt_showdisassemble)
2136 fieldinfo *fi = iptr[1].val.a;
2138 disp = dseg_addaddress(cd, &(fi->value));
2140 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2141 codegen_addpatchref(cd, mcodeptr,
2142 PATCHER_clinit, fi->class, 0);
2144 if (opt_showdisassemble)
2149 M_ALD(REG_ITMP1, REG_PV, disp);
2150 switch (iptr->op1) {
2152 M_IST(REG_ZERO, REG_ITMP1, 0);
2155 M_LST(REG_ZERO, REG_ITMP1, 0);
2158 M_AST(REG_ZERO, REG_ITMP1, 0);
2161 M_FST(REG_ZERO, REG_ITMP1, 0);
2164 M_DST(REG_ZERO, REG_ITMP1, 0);
2170 case ICMD_GETFIELD: /* ... ==> ..., value */
2171 /* op1 = type, val.i = field offset */
2173 var_to_reg_int(s1, src, REG_ITMP1);
2174 gen_nullptr_check(s1);
2176 if (iptr->val.a == NULL) {
2177 codegen_addpatchref(cd, mcodeptr,
2178 PATCHER_get_putfield,
2179 (unresolved_field *) iptr->target, 0);
2181 if (opt_showdisassemble)
2187 disp = ((fieldinfo *) (iptr->val.a))->offset;
2190 switch (iptr->op1) {
2192 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2194 store_reg_to_var_int(iptr->dst, d);
2197 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2199 store_reg_to_var_int(iptr->dst, d);
2202 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2204 store_reg_to_var_int(iptr->dst, d);
2207 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2209 store_reg_to_var_flt(iptr->dst, d);
2212 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2214 store_reg_to_var_flt(iptr->dst, d);
2219 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2220 /* op1 = type, val.a = field address */
2222 var_to_reg_int(s1, src->prev, REG_ITMP1);
2223 gen_nullptr_check(s1);
2225 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
2226 var_to_reg_int(s2, src, REG_ITMP2);
2228 var_to_reg_flt(s2, src, REG_FTMP2);
2231 if (iptr->val.a == NULL) {
2232 codegen_addpatchref(cd, mcodeptr,
2233 PATCHER_get_putfield,
2234 (unresolved_field *) iptr->target, 0);
2236 if (opt_showdisassemble)
2242 disp = ((fieldinfo *) (iptr->val.a))->offset;
2245 switch (iptr->op1) {
2247 M_IST(s2, s1, disp);
2250 M_LST(s2, s1, disp);
2253 M_AST(s2, s1, disp);
2256 M_FST(s2, s1, disp);
2259 M_DST(s2, s1, disp);
2264 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2265 /* val = value (in current instruction) */
2266 /* op1 = type, val.a = field address (in */
2267 /* following NOP) */
2269 var_to_reg_int(s1, src, REG_ITMP1);
2270 gen_nullptr_check(s1);
2272 if (iptr[1].val.a == NULL) {
2273 codegen_addpatchref(cd, mcodeptr,
2274 PATCHER_get_putfield,
2275 (unresolved_field *) iptr[1].target, 0);
2277 if (opt_showdisassemble)
2283 disp = ((fieldinfo *) (iptr[1].val.a))->offset;
2286 switch (iptr[1].op1) {
2288 M_IST(REG_ZERO, s1, disp);
2291 M_LST(REG_ZERO, s1, disp);
2294 M_AST(REG_ZERO, s1, disp);
2297 M_FST(REG_ZERO, s1, disp);
2300 M_DST(REG_ZERO, s1, disp);
2306 /* branch operations **************************************************/
2308 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2310 var_to_reg_int(s1, src, REG_ITMP1);
2311 M_INTMOVE(s1, REG_ITMP1_XPTR);
2313 #ifdef ENABLE_VERIFIER
2315 codegen_addpatchref(cd, mcodeptr,
2316 PATCHER_athrow_areturn,
2317 (unresolved_class *) iptr->val.a, 0);
2319 if (opt_showdisassemble)
2322 #endif /* ENABLE_VERIFIER */
2324 disp = dseg_addaddress(cd, asm_handle_exception);
2325 M_ALD(REG_ITMP2, REG_PV, disp);
2326 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2327 M_NOP; /* nop ensures that XPC is less than the end */
2328 /* of basic block */
2332 case ICMD_GOTO: /* ... ==> ... */
2333 /* op1 = target JavaVM pc */
2335 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2339 case ICMD_JSR: /* ... ==> ... */
2340 /* op1 = target JavaVM pc */
2342 M_BSR(REG_ITMP1, 0);
2343 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2346 case ICMD_RET: /* ... ==> ... */
2347 /* op1 = local variable */
2349 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2350 if (var->flags & INMEMORY) {
2351 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2352 M_RET(REG_ZERO, REG_ITMP1);
2355 M_RET(REG_ZERO, var->regoff);
2359 case ICMD_IFNULL: /* ..., value ==> ... */
2360 /* op1 = target JavaVM pc */
2362 var_to_reg_int(s1, src, REG_ITMP1);
2364 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2367 case ICMD_IFNONNULL: /* ..., value ==> ... */
2368 /* op1 = target JavaVM pc */
2370 var_to_reg_int(s1, src, REG_ITMP1);
2372 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2375 case ICMD_IFEQ: /* ..., value ==> ... */
2376 /* op1 = target JavaVM pc, val.i = constant */
2378 var_to_reg_int(s1, src, REG_ITMP1);
2379 if (iptr->val.i == 0) {
2383 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2384 M_CMPEQ_IMM(s1, iptr->val.i, REG_ITMP1);
2387 ICONST(REG_ITMP2, iptr->val.i);
2388 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2390 M_BNEZ(REG_ITMP1, 0);
2392 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2395 case ICMD_IFLT: /* ..., value ==> ... */
2396 /* op1 = target JavaVM pc, val.i = constant */
2398 var_to_reg_int(s1, src, REG_ITMP1);
2399 if (iptr->val.i == 0) {
2403 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2404 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2407 ICONST(REG_ITMP2, iptr->val.i);
2408 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2410 M_BNEZ(REG_ITMP1, 0);
2412 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2415 case ICMD_IFLE: /* ..., value ==> ... */
2416 /* op1 = target JavaVM pc, val.i = constant */
2418 var_to_reg_int(s1, src, REG_ITMP1);
2419 if (iptr->val.i == 0) {
2423 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2424 M_CMPLE_IMM(s1, iptr->val.i, REG_ITMP1);
2427 ICONST(REG_ITMP2, iptr->val.i);
2428 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2430 M_BNEZ(REG_ITMP1, 0);
2432 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2435 case ICMD_IFNE: /* ..., value ==> ... */
2436 /* op1 = target JavaVM pc, val.i = constant */
2438 var_to_reg_int(s1, src, REG_ITMP1);
2439 if (iptr->val.i == 0) {
2443 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2444 M_CMPEQ_IMM(s1, iptr->val.i, REG_ITMP1);
2447 ICONST(REG_ITMP2, iptr->val.i);
2448 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2450 M_BEQZ(REG_ITMP1, 0);
2452 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2455 case ICMD_IFGT: /* ..., value ==> ... */
2456 /* op1 = target JavaVM pc, val.i = constant */
2458 var_to_reg_int(s1, src, REG_ITMP1);
2459 if (iptr->val.i == 0) {
2463 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2464 M_CMPLE_IMM(s1, iptr->val.i, REG_ITMP1);
2467 ICONST(REG_ITMP2, iptr->val.i);
2468 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2470 M_BEQZ(REG_ITMP1, 0);
2472 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2475 case ICMD_IFGE: /* ..., value ==> ... */
2476 /* op1 = target JavaVM pc, val.i = constant */
2478 var_to_reg_int(s1, src, REG_ITMP1);
2479 if (iptr->val.i == 0) {
2483 if ((iptr->val.i > 0) && (iptr->val.i <= 255)) {
2484 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2487 ICONST(REG_ITMP2, iptr->val.i);
2488 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2490 M_BEQZ(REG_ITMP1, 0);
2492 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2495 case ICMD_IF_LEQ: /* ..., value ==> ... */
2496 /* op1 = target JavaVM pc, val.l = constant */
2498 var_to_reg_int(s1, src, REG_ITMP1);
2499 if (iptr->val.l == 0) {
2503 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2504 M_CMPEQ_IMM(s1, iptr->val.l, REG_ITMP1);
2507 LCONST(REG_ITMP2, iptr->val.l);
2508 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2510 M_BNEZ(REG_ITMP1, 0);
2512 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2515 case ICMD_IF_LLT: /* ..., value ==> ... */
2516 /* op1 = target JavaVM pc, val.l = constant */
2518 var_to_reg_int(s1, src, REG_ITMP1);
2519 if (iptr->val.l == 0) {
2523 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2524 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2527 LCONST(REG_ITMP2, iptr->val.l);
2528 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2530 M_BNEZ(REG_ITMP1, 0);
2532 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2535 case ICMD_IF_LLE: /* ..., value ==> ... */
2536 /* op1 = target JavaVM pc, val.l = constant */
2538 var_to_reg_int(s1, src, REG_ITMP1);
2539 if (iptr->val.l == 0) {
2543 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2544 M_CMPLE_IMM(s1, iptr->val.l, REG_ITMP1);
2547 LCONST(REG_ITMP2, iptr->val.l);
2548 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2550 M_BNEZ(REG_ITMP1, 0);
2552 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2555 case ICMD_IF_LNE: /* ..., value ==> ... */
2556 /* op1 = target JavaVM pc, val.l = constant */
2558 var_to_reg_int(s1, src, REG_ITMP1);
2559 if (iptr->val.l == 0) {
2563 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2564 M_CMPEQ_IMM(s1, iptr->val.l, REG_ITMP1);
2567 LCONST(REG_ITMP2, iptr->val.l);
2568 M_CMPEQ(s1, REG_ITMP2, REG_ITMP1);
2570 M_BEQZ(REG_ITMP1, 0);
2572 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2575 case ICMD_IF_LGT: /* ..., value ==> ... */
2576 /* op1 = target JavaVM pc, val.l = constant */
2578 var_to_reg_int(s1, src, REG_ITMP1);
2579 if (iptr->val.l == 0) {
2583 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2584 M_CMPLE_IMM(s1, iptr->val.l, REG_ITMP1);
2587 LCONST(REG_ITMP2, iptr->val.l);
2588 M_CMPLE(s1, REG_ITMP2, REG_ITMP1);
2590 M_BEQZ(REG_ITMP1, 0);
2592 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2595 case ICMD_IF_LGE: /* ..., value ==> ... */
2596 /* op1 = target JavaVM pc, val.l = constant */
2598 var_to_reg_int(s1, src, REG_ITMP1);
2599 if (iptr->val.l == 0) {
2603 if ((iptr->val.l > 0) && (iptr->val.l <= 255)) {
2604 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2607 LCONST(REG_ITMP2, iptr->val.l);
2608 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2610 M_BEQZ(REG_ITMP1, 0);
2612 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2615 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2616 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2617 case ICMD_IF_ACMPEQ:
2619 var_to_reg_int(s1, src->prev, REG_ITMP1);
2620 var_to_reg_int(s2, src, REG_ITMP2);
2621 M_CMPEQ(s1, s2, REG_ITMP1);
2622 M_BNEZ(REG_ITMP1, 0);
2623 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2626 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2627 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2628 case ICMD_IF_ACMPNE:
2630 var_to_reg_int(s1, src->prev, REG_ITMP1);
2631 var_to_reg_int(s2, src, REG_ITMP2);
2632 M_CMPEQ(s1, s2, REG_ITMP1);
2633 M_BEQZ(REG_ITMP1, 0);
2634 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2637 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2638 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2640 var_to_reg_int(s1, src->prev, REG_ITMP1);
2641 var_to_reg_int(s2, src, REG_ITMP2);
2642 M_CMPLT(s1, s2, REG_ITMP1);
2643 M_BNEZ(REG_ITMP1, 0);
2644 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2647 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2648 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2650 var_to_reg_int(s1, src->prev, REG_ITMP1);
2651 var_to_reg_int(s2, src, REG_ITMP2);
2652 M_CMPLE(s1, s2, REG_ITMP1);
2653 M_BEQZ(REG_ITMP1, 0);
2654 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2657 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2658 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2660 var_to_reg_int(s1, src->prev, REG_ITMP1);
2661 var_to_reg_int(s2, src, REG_ITMP2);
2662 M_CMPLE(s1, s2, REG_ITMP1);
2663 M_BNEZ(REG_ITMP1, 0);
2664 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2667 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2668 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2670 var_to_reg_int(s1, src->prev, REG_ITMP1);
2671 var_to_reg_int(s2, src, REG_ITMP2);
2672 M_CMPLT(s1, s2, REG_ITMP1);
2673 M_BEQZ(REG_ITMP1, 0);
2674 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2677 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2679 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2682 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2683 /* val.i = constant */
2685 var_to_reg_int(s1, src, REG_ITMP1);
2686 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2688 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2689 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2690 M_CMPEQ(s1, REG_ZERO, d);
2691 store_reg_to_var_int(iptr->dst, d);
2694 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2695 M_CMPEQ(s1, REG_ZERO, d);
2697 store_reg_to_var_int(iptr->dst, d);
2701 M_MOV(s1, REG_ITMP1);
2704 ICONST(d, iptr[1].val.i);
2706 if ((s3 >= 0) && (s3 <= 255)) {
2707 M_CMOVEQ_IMM(s1, s3, d);
2709 ICONST(REG_ITMP3, s3);
2710 M_CMOVEQ(s1, REG_ITMP3, d);
2712 store_reg_to_var_int(iptr->dst, d);
2715 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2716 /* val.i = constant */
2718 var_to_reg_int(s1, src, REG_ITMP1);
2719 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2721 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2722 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2723 M_CMPEQ(s1, REG_ZERO, d);
2724 store_reg_to_var_int(iptr->dst, d);
2727 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2728 M_CMPEQ(s1, REG_ZERO, d);
2730 store_reg_to_var_int(iptr->dst, d);
2734 M_MOV(s1, REG_ITMP1);
2737 ICONST(d, iptr[1].val.i);
2739 if ((s3 >= 0) && (s3 <= 255)) {
2740 M_CMOVNE_IMM(s1, s3, d);
2742 ICONST(REG_ITMP3, s3);
2743 M_CMOVNE(s1, REG_ITMP3, d);
2745 store_reg_to_var_int(iptr->dst, d);
2748 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2749 /* val.i = constant */
2751 var_to_reg_int(s1, src, REG_ITMP1);
2752 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2754 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2755 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2756 M_CMPLT(s1, REG_ZERO, d);
2757 store_reg_to_var_int(iptr->dst, d);
2760 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2761 M_CMPLE(REG_ZERO, s1, d);
2762 store_reg_to_var_int(iptr->dst, d);
2766 M_MOV(s1, REG_ITMP1);
2769 ICONST(d, iptr[1].val.i);
2771 if ((s3 >= 0) && (s3 <= 255)) {
2772 M_CMOVLT_IMM(s1, s3, d);
2774 ICONST(REG_ITMP3, s3);
2775 M_CMOVLT(s1, REG_ITMP3, d);
2777 store_reg_to_var_int(iptr->dst, d);
2780 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2781 /* val.i = constant */
2783 var_to_reg_int(s1, src, REG_ITMP1);
2784 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2786 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2787 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2788 M_CMPLE(REG_ZERO, s1, d);
2789 store_reg_to_var_int(iptr->dst, d);
2792 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2793 M_CMPLT(s1, REG_ZERO, d);
2794 store_reg_to_var_int(iptr->dst, d);
2798 M_MOV(s1, REG_ITMP1);
2801 ICONST(d, iptr[1].val.i);
2803 if ((s3 >= 0) && (s3 <= 255)) {
2804 M_CMOVGE_IMM(s1, s3, d);
2806 ICONST(REG_ITMP3, s3);
2807 M_CMOVGE(s1, REG_ITMP3, d);
2809 store_reg_to_var_int(iptr->dst, d);
2812 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2813 /* val.i = constant */
2815 var_to_reg_int(s1, src, REG_ITMP1);
2816 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2818 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2819 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2820 M_CMPLT(REG_ZERO, s1, d);
2821 store_reg_to_var_int(iptr->dst, d);
2824 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2825 M_CMPLE(s1, REG_ZERO, d);
2826 store_reg_to_var_int(iptr->dst, d);
2830 M_MOV(s1, REG_ITMP1);
2833 ICONST(d, iptr[1].val.i);
2835 if ((s3 >= 0) && (s3 <= 255)) {
2836 M_CMOVGT_IMM(s1, s3, d);
2838 ICONST(REG_ITMP3, s3);
2839 M_CMOVGT(s1, REG_ITMP3, d);
2841 store_reg_to_var_int(iptr->dst, d);
2844 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2845 /* val.i = constant */
2847 var_to_reg_int(s1, src, REG_ITMP1);
2848 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
2850 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2851 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2852 M_CMPLE(s1, REG_ZERO, d);
2853 store_reg_to_var_int(iptr->dst, d);
2856 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2857 M_CMPLT(REG_ZERO, s1, d);
2858 store_reg_to_var_int(iptr->dst, d);
2862 M_MOV(s1, REG_ITMP1);
2865 ICONST(d, iptr[1].val.i);
2867 if ((s3 >= 0) && (s3 <= 255)) {
2868 M_CMOVLE_IMM(s1, s3, d);
2870 ICONST(REG_ITMP3, s3);
2871 M_CMOVLE(s1, REG_ITMP3, d);
2873 store_reg_to_var_int(iptr->dst, d);
2877 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2880 var_to_reg_int(s1, src, REG_RESULT);
2881 M_INTMOVE(s1, REG_RESULT);
2882 goto nowperformreturn;
2884 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2886 var_to_reg_int(s1, src, REG_RESULT);
2887 M_INTMOVE(s1, REG_RESULT);
2889 #ifdef ENABLE_VERIFIER
2891 codegen_addpatchref(cd, mcodeptr,
2892 PATCHER_athrow_areturn,
2893 (unresolved_class *) iptr->val.a, 0);
2895 if (opt_showdisassemble)
2898 #endif /* ENABLE_VERIFIER */
2899 goto nowperformreturn;
2901 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2904 var_to_reg_flt(s1, src, REG_FRESULT);
2905 M_FLTMOVE(s1, REG_FRESULT);
2906 goto nowperformreturn;
2908 case ICMD_RETURN: /* ... ==> ... */
2914 p = parentargs_base;
2916 /* call trace function */
2919 M_LDA(REG_SP, REG_SP, -3 * 8);
2920 M_AST(REG_RA, REG_SP, 0 * 8);
2921 M_LST(REG_RESULT, REG_SP, 1 * 8);
2922 M_DST(REG_FRESULT, REG_SP, 2 * 8);
2924 disp = dseg_addaddress(cd, m);
2925 M_ALD(rd->argintregs[0], REG_PV, disp);
2926 M_MOV(REG_RESULT, rd->argintregs[1]);
2927 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2928 M_FLTMOVE(REG_FRESULT, rd->argfltregs[3]);
2930 disp = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2931 M_ALD(REG_PV, REG_PV, disp);
2932 M_JSR(REG_RA, REG_PV);
2933 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2934 M_LDA(REG_PV, REG_RA, -disp);
2936 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
2937 M_LLD(REG_RESULT, REG_SP, 1 * 8);
2938 M_ALD(REG_RA, REG_SP, 0 * 8);
2939 M_LDA(REG_SP, REG_SP, 3 * 8);
2942 #if defined(USE_THREADS)
2943 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2944 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2946 switch (iptr->opc) {
2950 M_LST(REG_RESULT, REG_SP, rd->memuse * 8);
2954 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
2958 disp = dseg_addaddress(cd, BUILTIN_monitorexit);
2959 M_ALD(REG_PV, REG_PV, disp);
2960 M_JSR(REG_RA, REG_PV);
2961 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2962 M_LDA(REG_PV, REG_RA, disp);
2964 switch (iptr->opc) {
2968 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
2972 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
2978 /* restore return address */
2980 if (!m->isleafmethod) {
2981 p--; M_LLD(REG_RA, REG_SP, p * 8);
2984 /* restore saved registers */
2986 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2987 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
2989 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2990 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2993 /* deallocate stack */
2995 if (parentargs_base) {
2996 M_LDA(REG_SP, REG_SP, parentargs_base * 8);
2999 M_RET(REG_ZERO, REG_RA);
3005 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3010 tptr = (void **) iptr->target;
3012 s4ptr = iptr->val.a;
3013 l = s4ptr[1]; /* low */
3014 i = s4ptr[2]; /* high */
3016 var_to_reg_int(s1, src, REG_ITMP1);
3018 M_INTMOVE(s1, REG_ITMP1);
3019 } else if (l <= 32768) {
3020 M_LDA(REG_ITMP1, s1, -l);
3022 ICONST(REG_ITMP2, l);
3023 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
3030 M_CMPULE_IMM(REG_ITMP1, i - 1, REG_ITMP2);
3032 M_LDA(REG_ITMP2, REG_ZERO, i - 1);
3033 M_CMPULE(REG_ITMP1, REG_ITMP2, REG_ITMP2);
3035 M_BEQZ(REG_ITMP2, 0);
3036 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
3038 /* build jump table top down and use address of lowest entry */
3040 /* s4ptr += 3 + i; */
3044 dseg_addtarget(cd, (basicblock *) tptr[0]);
3049 /* length of dataseg after last dseg_addtarget is used by load */
3051 M_SAADDQ(REG_ITMP1, REG_PV, REG_ITMP2);
3052 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
3053 M_JMP(REG_ZERO, REG_ITMP2);
3058 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3060 s4 i, l, val, *s4ptr;
3063 tptr = (void **) iptr->target;
3065 s4ptr = iptr->val.a;
3066 l = s4ptr[0]; /* default */
3067 i = s4ptr[1]; /* count */
3069 MCODECHECK((i<<2)+8);
3070 var_to_reg_int(s1, src, REG_ITMP1);
3076 if ((val >= 0) && (val <= 255)) {
3077 M_CMPEQ_IMM(s1, val, REG_ITMP2);
3079 if ((val >= -32768) && (val <= 32767)) {
3080 M_LDA(REG_ITMP2, REG_ZERO, val);
3082 disp = dseg_adds4(cd, val);
3083 M_ILD(REG_ITMP2, REG_PV, disp);
3085 M_CMPEQ(s1, REG_ITMP2, REG_ITMP2);
3087 M_BNEZ(REG_ITMP2, 0);
3088 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
3093 tptr = (void **) iptr->target;
3094 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
3101 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
3102 /* op1 = arg count val.a = builtintable entry */
3108 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3109 /* op1 = arg count, val.a = method pointer */
3111 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3112 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
3113 case ICMD_INVOKEINTERFACE:
3118 unresolved_method *um = iptr->target;
3119 md = um->methodref->parseddesc.md;
3121 md = lm->parseddesc;
3125 s3 = md->paramcount;
3127 MCODECHECK((s3 << 1) + 64);
3129 /* copy arguments to registers or stack location */
3131 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
3132 if (src->varkind == ARGVAR)
3134 if (IS_INT_LNG_TYPE(src->type)) {
3135 if (!md->params[s3].inmemory) {
3136 s1 = rd->argintregs[md->params[s3].regoff];
3137 var_to_reg_int(d, src, s1);
3140 var_to_reg_int(d, src, REG_ITMP1);
3141 M_LST(d, REG_SP, md->params[s3].regoff * 8);
3145 if (!md->params[s3].inmemory) {
3146 s1 = rd->argfltregs[md->params[s3].regoff];
3147 var_to_reg_flt(d, src, s1);
3150 var_to_reg_flt(d, src, REG_FTMP1);
3151 M_DST(d, REG_SP, md->params[s3].regoff * 8);
3156 switch (iptr->opc) {
3158 disp = dseg_addaddress(cd, bte->fp);
3159 d = md->returntype.type;
3161 M_ALD(REG_PV, REG_PV, disp); /* Pointer to built-in-function */
3162 M_JSR(REG_RA, REG_PV);
3163 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3164 M_LDA(REG_PV, REG_RA, -disp);
3166 /* if op1 == true, we need to check for an exception */
3168 if (iptr->op1 == true) {
3169 M_BEQZ(REG_RESULT, 0);
3170 codegen_addxexceptionrefs(cd, mcodeptr);
3174 case ICMD_INVOKESPECIAL:
3175 M_BEQZ(rd->argintregs[0], 0);
3176 codegen_addxnullrefs(cd, mcodeptr);
3179 case ICMD_INVOKESTATIC:
3181 unresolved_method *um = iptr->target;
3183 disp = dseg_addaddress(cd, NULL);
3185 codegen_addpatchref(cd, mcodeptr,
3186 PATCHER_invokestatic_special, um, disp);
3188 if (opt_showdisassemble)
3191 d = um->methodref->parseddesc.md->returntype.type;
3194 disp = dseg_addaddress(cd, lm->stubroutine);
3195 d = lm->parseddesc->returntype.type;
3198 M_ALD(REG_PV, REG_PV, disp); /* method pointer in r27 */
3199 M_JSR(REG_RA, REG_PV);
3200 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3201 M_LDA(REG_PV, REG_RA, -disp);
3204 case ICMD_INVOKEVIRTUAL:
3205 gen_nullptr_check(rd->argintregs[0]);
3208 unresolved_method *um = iptr->target;
3210 codegen_addpatchref(cd, mcodeptr,
3211 PATCHER_invokevirtual, um, 0);
3213 if (opt_showdisassemble)
3217 d = um->methodref->parseddesc.md->returntype.type;
3220 s1 = OFFSET(vftbl_t, table[0]) +
3221 sizeof(methodptr) * lm->vftblindex;
3222 d = lm->parseddesc->returntype.type;
3225 M_ALD(REG_METHODPTR, rd->argintregs[0],
3226 OFFSET(java_objectheader, vftbl));
3227 M_ALD(REG_PV, REG_METHODPTR, s1);
3228 M_JSR(REG_RA, REG_PV);
3229 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3230 M_LDA(REG_PV, REG_RA, -disp);
3233 case ICMD_INVOKEINTERFACE:
3234 gen_nullptr_check(rd->argintregs[0]);
3237 unresolved_method *um = iptr->target;
3239 codegen_addpatchref(cd, mcodeptr,
3240 PATCHER_invokeinterface, um, 0);
3242 if (opt_showdisassemble)
3247 d = um->methodref->parseddesc.md->returntype.type;
3250 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3251 sizeof(methodptr*) * lm->class->index;
3253 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3255 d = lm->parseddesc->returntype.type;
3258 M_ALD(REG_METHODPTR, rd->argintregs[0],
3259 OFFSET(java_objectheader, vftbl));
3260 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3261 M_ALD(REG_PV, REG_METHODPTR, s2);
3262 M_JSR(REG_RA, REG_PV);
3263 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3264 M_LDA(REG_PV, REG_RA, -disp);
3268 /* d contains return type */
3270 if (d != TYPE_VOID) {
3271 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3272 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3273 M_INTMOVE(REG_RESULT, s1);
3274 store_reg_to_var_int(iptr->dst, s1);
3276 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3277 M_FLTMOVE(REG_FRESULT, s1);
3278 store_reg_to_var_flt(iptr->dst, s1);
3284 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3286 /* op1: 0 == array, 1 == class */
3287 /* val.a: (classinfo*) superclass */
3289 /* superclass is an interface:
3291 * OK if ((sub == NULL) ||
3292 * (sub->vftbl->interfacetablelength > super->index) &&
3293 * (sub->vftbl->interfacetable[-super->index] != NULL));
3295 * superclass is a class:
3297 * OK if ((sub == NULL) || (0
3298 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3299 * super->vftbl->diffval));
3302 if (iptr->op1 == 1) {
3303 /* object type cast-check */
3306 vftbl_t *supervftbl;
3309 super = (classinfo *) iptr->val.a;
3316 superindex = super->index;
3317 supervftbl = super->vftbl;
3320 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3321 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3323 var_to_reg_int(s1, src, REG_ITMP1);
3325 /* calculate interface checkcast code size */
3329 s2 += opt_showdisassemble ? 1 : 0;
3331 /* calculate class checkcast code size */
3333 s3 = 9 /* 8 + (s1 == REG_ITMP1) */;
3335 s3 += opt_showdisassemble ? 1 : 0;
3337 /* if class is not resolved, check which code to call */
3340 M_BEQZ(s1, 4 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
3342 disp = dseg_adds4(cd, 0); /* super->flags */
3344 codegen_addpatchref(cd, mcodeptr,
3345 PATCHER_checkcast_instanceof_flags,
3346 (constant_classref *) iptr->target,
3349 if (opt_showdisassemble)
3352 M_ILD(REG_ITMP2, REG_PV, disp);
3353 disp = dseg_adds4(cd, ACC_INTERFACE);
3354 M_ILD(REG_ITMP3, REG_PV, disp);
3355 M_AND(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3356 M_BEQZ(REG_ITMP2, s2 + 1);
3359 /* interface checkcast code */
3361 if (!super || (super->flags & ACC_INTERFACE)) {
3366 codegen_addpatchref(cd, mcodeptr,
3367 PATCHER_checkcast_instanceof_interface,
3368 (constant_classref *) iptr->target,
3371 if (opt_showdisassemble)
3375 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3376 M_ILD(REG_ITMP3, REG_ITMP2,
3377 OFFSET(vftbl_t, interfacetablelength));
3378 M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
3379 M_BLEZ(REG_ITMP3, 0);
3380 codegen_addxcastrefs(cd, mcodeptr);
3381 M_ALD(REG_ITMP3, REG_ITMP2,
3382 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3383 superindex * sizeof(methodptr*)));
3384 M_BEQZ(REG_ITMP3, 0);
3385 codegen_addxcastrefs(cd, mcodeptr);
3391 /* class checkcast code */
3393 if (!super || !(super->flags & ACC_INTERFACE)) {
3394 disp = dseg_addaddress(cd, supervftbl);
3400 codegen_addpatchref(cd, mcodeptr,
3401 PATCHER_checkcast_instanceof_class,
3402 (constant_classref *) iptr->target,
3405 if (opt_showdisassemble)
3409 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3410 M_ALD(REG_ITMP3, REG_PV, disp);
3411 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3412 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3414 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3415 /* if (s1 != REG_ITMP1) { */
3416 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3417 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3418 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3419 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3421 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3424 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3425 M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3426 M_ALD(REG_ITMP3, REG_PV, disp);
3427 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3428 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3429 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3432 M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3);
3433 M_BEQZ(REG_ITMP3, 0);
3434 codegen_addxcastrefs(cd, mcodeptr);
3436 d = reg_of_var(rd, iptr->dst, s1);
3439 /* array type cast-check */
3441 var_to_reg_int(s1, src, rd->argintregs[0]);
3442 M_INTMOVE(s1, rd->argintregs[0]);
3444 disp = dseg_addaddress(cd, iptr->val.a);
3446 if (iptr->val.a == NULL) {
3447 codegen_addpatchref(cd, mcodeptr,
3448 PATCHER_builtin_arraycheckcast,
3449 (constant_classref *) iptr->target,
3452 if (opt_showdisassemble)
3456 M_ALD(rd->argintregs[1], REG_PV, disp);
3457 disp = dseg_addaddress(cd, BUILTIN_arraycheckcast);
3458 M_ALD(REG_PV, REG_PV, disp);
3459 M_JSR(REG_RA, REG_PV);
3460 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3461 M_LDA(REG_PV, REG_RA, -disp);
3463 M_BEQZ(REG_RESULT, 0);
3464 codegen_addxcastrefs(cd, mcodeptr);
3466 var_to_reg_int(s1, src, REG_ITMP1);
3467 d = reg_of_var(rd, iptr->dst, s1);
3470 store_reg_to_var_int(iptr->dst, d);
3473 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3475 /* op1: 0 == array, 1 == class */
3476 /* val.a: (classinfo*) superclass */
3478 /* superclass is an interface:
3480 * return (sub != NULL) &&
3481 * (sub->vftbl->interfacetablelength > super->index) &&
3482 * (sub->vftbl->interfacetable[-super->index] != NULL);
3484 * superclass is a class:
3486 * return ((sub != NULL) && (0
3487 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3488 * super->vftbl->diffvall));
3493 vftbl_t *supervftbl;
3496 super = (classinfo *) iptr->val.a;
3503 superindex = super->index;
3504 supervftbl = super->vftbl;
3507 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3508 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3510 var_to_reg_int(s1, src, REG_ITMP1);
3511 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3513 M_MOV(s1, REG_ITMP1);
3517 /* calculate interface instanceof code size */
3521 s2 += (d == REG_ITMP2 ? 1 : 0) + (opt_showdisassemble ? 1 : 0);
3523 /* calculate class instanceof code size */
3527 s3 += (opt_showdisassemble ? 1 : 0);
3529 /* if class is not resolved, check which code to call */
3533 M_BEQZ(s1, 4 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
3535 disp = dseg_adds4(cd, 0); /* super->flags */
3537 codegen_addpatchref(cd, mcodeptr,
3538 PATCHER_checkcast_instanceof_flags,
3539 (constant_classref *) iptr->target, disp);
3541 if (opt_showdisassemble)
3544 M_ILD(REG_ITMP3, REG_PV, disp);
3546 disp = dseg_adds4(cd, ACC_INTERFACE);
3547 M_ILD(REG_ITMP2, REG_PV, disp);
3548 M_AND(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3549 M_BEQZ(REG_ITMP3, s2 + 1);
3552 /* interface instanceof code */
3554 if (!super || (super->flags & ACC_INTERFACE)) {
3560 /* If d == REG_ITMP2, then it's destroyed in check code */
3565 codegen_addpatchref(cd, mcodeptr,
3566 PATCHER_checkcast_instanceof_interface,
3567 (constant_classref *) iptr->target, 0);
3569 if (opt_showdisassemble)
3573 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3574 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3575 M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
3576 M_BLEZ(REG_ITMP3, 2);
3577 M_ALD(REG_ITMP1, REG_ITMP1,
3578 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3579 superindex * sizeof(methodptr*)));
3580 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3586 /* class instanceof code */
3588 if (!super || !(super->flags & ACC_INTERFACE)) {
3589 disp = dseg_addaddress(cd, supervftbl);
3596 codegen_addpatchref(cd, mcodeptr,
3597 PATCHER_checkcast_instanceof_class,
3598 (constant_classref *) iptr->target,
3601 if (opt_showdisassemble)
3605 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3606 M_ALD(REG_ITMP2, REG_PV, disp);
3607 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3608 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3610 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3611 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3612 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3613 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3614 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3616 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3617 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3619 store_reg_to_var_int(iptr->dst, d);
3623 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3624 /* op1 = dimension, val.a = class */
3626 /* check for negative sizes and copy sizes to stack if necessary */
3628 MCODECHECK((iptr->op1 << 1) + 64);
3630 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3631 /* copy SAVEDVAR sizes to stack */
3633 if (src->varkind != ARGVAR) {
3634 var_to_reg_int(s2, src, REG_ITMP1);
3635 M_LST(s2, REG_SP, s1 * 8);
3639 /* a0 = dimension count */
3641 ICONST(rd->argintregs[0], iptr->op1);
3643 /* is patcher function set? */
3645 if (iptr->val.a == NULL) {
3646 disp = dseg_addaddress(cd, 0);
3648 codegen_addpatchref(cd, mcodeptr,
3649 PATCHER_builtin_multianewarray,
3650 (constant_classref *) iptr->target,
3653 if (opt_showdisassemble)
3657 disp = dseg_addaddress(cd, iptr->val.a);
3660 /* a1 = arraydescriptor */
3662 M_ALD(rd->argintregs[1], REG_PV, disp);
3664 /* a2 = pointer to dimensions = stack pointer */
3666 M_INTMOVE(REG_SP, rd->argintregs[2]);
3668 disp = dseg_addaddress(cd, BUILTIN_multianewarray);
3669 M_ALD(REG_PV, REG_PV, disp);
3670 M_JSR(REG_RA, REG_PV);
3671 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3672 M_LDA(REG_PV, REG_RA, -disp);
3674 /* check for exception before result assignment */
3676 M_BEQZ(REG_RESULT, 0);
3677 codegen_addxexceptionrefs(cd, mcodeptr);
3679 d = reg_of_var(rd, iptr->dst, REG_RESULT);
3680 M_INTMOVE(REG_RESULT, d);
3681 store_reg_to_var_int(iptr->dst, d);
3686 new_internalerror("Unknown ICMD %d", iptr->opc);
3690 } /* for instruction */
3692 /* copy values to interface registers */
3694 src = bptr->outstack;
3695 len = bptr->outdepth;
3697 #if defined(ENABLE_LSRA)
3702 if ((src->varkind != STACKVAR)) {
3704 if (IS_FLT_DBL_TYPE(s2)) {
3705 var_to_reg_flt(s1, src, REG_FTMP1);
3706 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3707 M_FLTMOVE(s1,rd->interfaces[len][s2].regoff);
3710 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3714 var_to_reg_int(s1, src, REG_ITMP1);
3715 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3716 M_INTMOVE(s1,rd->interfaces[len][s2].regoff);
3719 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3725 } /* if (bptr -> flags >= BBREACHED) */
3726 } /* for basic block */
3728 dseg_createlinenumbertable(cd);
3732 s4 *xcodeptr = NULL;
3735 /* generate ArithmeticException stubs */
3737 for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3738 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3740 (u1 *) mcodeptr - cd->mcodebase);
3744 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3746 if (xcodeptr != NULL) {
3747 disp = xcodeptr - mcodeptr - 1;
3751 xcodeptr = mcodeptr;
3753 M_MOV(REG_PV, rd->argintregs[0]);
3754 M_MOV(REG_SP, rd->argintregs[1]);
3755 M_ALD(rd->argintregs[2],
3756 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3757 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3759 M_LDA(REG_SP, REG_SP, -1 * 8);
3760 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3762 disp = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
3763 M_ALD(REG_PV, REG_PV, disp);
3764 M_JSR(REG_RA, REG_PV);
3765 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3766 M_LDA(REG_PV, REG_RA, -disp);
3768 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3770 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3771 M_LDA(REG_SP, REG_SP, 1 * 8);
3773 disp = dseg_addaddress(cd, asm_handle_exception);
3774 M_ALD(REG_ITMP3, REG_PV, disp);
3775 M_JMP(REG_ZERO, REG_ITMP3);
3779 /* generate ArrayIndexOutOfBoundsException stubs */
3783 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3784 gen_resolvebranch((u1*) cd->mcodebase + bref->branchpos,
3786 (u1*) mcodeptr - cd->mcodebase);
3790 /* move index register into REG_ITMP1 */
3792 M_MOV(bref->reg, REG_ITMP1);
3793 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3795 if (xcodeptr != NULL) {
3796 disp = xcodeptr - mcodeptr - 1;
3800 xcodeptr = mcodeptr;
3802 M_MOV(REG_PV, rd->argintregs[0]);
3803 M_MOV(REG_SP, rd->argintregs[1]);
3805 if (m->isleafmethod)
3806 M_MOV(REG_RA, rd->argintregs[2]);
3808 M_ALD(rd->argintregs[2],
3809 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3811 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3812 M_MOV(REG_ITMP1, rd->argintregs[4]);
3814 M_LDA(REG_SP, REG_SP, -2 * 8);
3815 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3817 if (m->isleafmethod)
3818 M_AST(REG_RA, REG_SP, 1 * 8);
3820 disp = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
3821 M_ALD(REG_PV, REG_PV, disp);
3822 M_JSR(REG_RA, REG_PV);
3823 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3824 M_LDA(REG_PV, REG_RA, -disp);
3826 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3828 if (m->isleafmethod)
3829 M_ALD(REG_RA, REG_SP, 1 * 8);
3831 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3832 M_LDA(REG_SP, REG_SP, 2 * 8);
3834 disp = dseg_addaddress(cd, asm_handle_exception);
3835 M_ALD(REG_ITMP3, REG_PV, disp);
3836 M_JMP(REG_ZERO, REG_ITMP3);
3840 /* generate ArrayStoreException stubs */
3844 for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
3845 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3847 (u1 *) mcodeptr - cd->mcodebase);
3851 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3853 if (xcodeptr != NULL) {
3854 disp = xcodeptr - mcodeptr - 1;
3858 xcodeptr = mcodeptr;
3860 M_MOV(REG_PV, rd->argintregs[0]);
3861 M_MOV(REG_SP, rd->argintregs[1]);
3862 M_ALD(rd->argintregs[2],
3863 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3864 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3866 M_LDA(REG_SP, REG_SP, -1 * 8);
3867 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3869 disp = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
3870 M_ALD(REG_PV, REG_PV, disp);
3871 M_JSR(REG_RA, REG_PV);
3872 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3873 M_LDA(REG_PV, REG_RA, -disp);
3875 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3877 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3878 M_LDA(REG_SP, REG_SP, 1 * 8);
3880 disp = dseg_addaddress(cd, asm_handle_exception);
3881 M_ALD(REG_ITMP3, REG_PV, disp);
3882 M_JMP(REG_ZERO, REG_ITMP3);
3886 /* generate ClassCastException stubs */
3890 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3891 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3893 (u1 *) mcodeptr - cd->mcodebase);
3897 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3899 if (xcodeptr != NULL) {
3900 disp = xcodeptr - mcodeptr - 1;
3904 xcodeptr = mcodeptr;
3906 M_MOV(REG_PV, rd->argintregs[0]);
3907 M_MOV(REG_SP, rd->argintregs[1]);
3909 if (m->isleafmethod)
3910 M_MOV(REG_RA, rd->argintregs[2]);
3912 M_ALD(rd->argintregs[2],
3913 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3915 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3917 M_LDA(REG_SP, REG_SP, -2 * 8);
3918 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3920 if (m->isleafmethod)
3921 M_AST(REG_RA, REG_SP, 1 * 8);
3923 disp = dseg_addaddress(cd, stacktrace_inline_classcastexception);
3924 M_ALD(REG_PV, REG_PV, disp);
3925 M_JSR(REG_RA, REG_PV);
3926 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3927 M_LDA(REG_PV, REG_RA, -disp);
3929 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3931 if (m->isleafmethod)
3932 M_ALD(REG_RA, REG_SP, 1 * 8);
3934 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3935 M_LDA(REG_SP, REG_SP, 2 * 8);
3937 disp = dseg_addaddress(cd, asm_handle_exception);
3938 M_ALD(REG_ITMP3, REG_PV, disp);
3939 M_JMP(REG_ZERO, REG_ITMP3);
3943 /* generate NullPointerException stubs */
3947 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3948 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3950 (u1 *) mcodeptr - cd->mcodebase);
3954 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3956 if (xcodeptr != NULL) {
3957 disp = xcodeptr - mcodeptr - 1;
3961 xcodeptr = mcodeptr;
3963 M_MOV(REG_PV, rd->argintregs[0]);
3964 M_MOV(REG_SP, rd->argintregs[1]);
3966 if (m->isleafmethod)
3967 M_MOV(REG_RA, rd->argintregs[2]);
3969 M_ALD(rd->argintregs[2],
3970 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
3972 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3974 M_LDA(REG_SP, REG_SP, -2 * 8);
3975 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3977 if (m->isleafmethod)
3978 M_AST(REG_RA, REG_SP, 1 * 8);
3980 disp = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
3981 M_ALD(REG_PV, REG_PV, disp);
3982 M_JSR(REG_RA, REG_PV);
3983 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3984 M_LDA(REG_PV, REG_RA, -disp);
3986 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3988 if (m->isleafmethod)
3989 M_ALD(REG_RA, REG_SP, 1 * 8);
3991 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3992 M_LDA(REG_SP, REG_SP, 2 * 8);
3994 disp = dseg_addaddress(cd, asm_handle_exception);
3995 M_ALD(REG_ITMP3, REG_PV, disp);
3996 M_JMP(REG_ZERO, REG_ITMP3);
4000 /* generate exception check stubs */
4004 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
4005 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
4007 (u1 *) mcodeptr - cd->mcodebase);
4011 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
4013 if (xcodeptr != NULL) {
4014 disp = xcodeptr - mcodeptr - 1;
4018 xcodeptr = mcodeptr;
4020 M_MOV(REG_PV, rd->argintregs[0]);
4021 M_MOV(REG_SP, rd->argintregs[1]);
4022 M_ALD(rd->argintregs[2],
4023 REG_SP, parentargs_base * 8 - SIZEOF_VOID_P);
4024 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
4026 M_LDA(REG_SP, REG_SP, -1 * 8);
4027 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
4029 disp = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
4030 M_ALD(REG_PV, REG_PV, disp);
4031 M_JSR(REG_RA, REG_PV);
4032 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4033 M_LDA(REG_PV, REG_RA, -disp);
4035 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
4037 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
4038 M_LDA(REG_SP, REG_SP, 1 * 8);
4040 disp = dseg_addaddress(cd, asm_handle_exception);
4041 M_ALD(REG_ITMP3, REG_PV, disp);
4042 M_JMP(REG_ZERO, REG_ITMP3);
4046 /* generate patcher stub call code */
4053 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4054 /* check code segment size */
4058 /* Get machine code which is patched back in later. The call is */
4059 /* 1 instruction word long. */
4061 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4064 /* patch in the call to call the following code (done at compile */
4067 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4068 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4070 M_BSR(REG_ITMP3, tmpmcodeptr - (xcodeptr + 1));
4072 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4074 /* create stack frame */
4076 M_LSUB_IMM(REG_SP, 6 * 8, REG_SP);
4078 /* move return address onto stack */
4080 M_AST(REG_ITMP3, REG_SP, 5 * 8);
4082 /* move pointer to java_objectheader onto stack */
4084 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4085 /* create a virtual java_objectheader */
4087 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4088 disp = dseg_addaddress(cd, NULL); /* vftbl */
4090 M_LDA(REG_ITMP3, REG_PV, disp);
4091 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4096 /* move machine code onto stack */
4098 disp = dseg_adds4(cd, mcode);
4099 M_ILD(REG_ITMP3, REG_PV, disp);
4100 M_IST(REG_ITMP3, REG_SP, 3 * 8);
4102 /* move class/method/field reference onto stack */
4104 disp = dseg_addaddress(cd, pref->ref);
4105 M_ALD(REG_ITMP3, REG_PV, disp);
4106 M_AST(REG_ITMP3, REG_SP, 2 * 8);
4108 /* move data segment displacement onto stack */
4110 disp = dseg_adds4(cd, pref->disp);
4111 M_ILD(REG_ITMP3, REG_PV, disp);
4112 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4114 /* move patcher function pointer onto stack */
4116 disp = dseg_addaddress(cd, pref->patcher);
4117 M_ALD(REG_ITMP3, REG_PV, disp);
4118 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4120 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4121 M_ALD(REG_ITMP3, REG_PV, disp);
4122 M_JMP(REG_ZERO, REG_ITMP3);
4127 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4129 /* everything's ok */
4135 /* createcompilerstub **********************************************************
4137 Creates a stub routine which calls the compiler.
4139 *******************************************************************************/
4141 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
4142 #define COMPILERSTUB_CODESIZE 3 * 4
4144 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4147 u1 *createcompilerstub(methodinfo *m)
4149 u1 *s; /* memory to hold the stub */
4151 s4 *mcodeptr; /* code generation pointer */
4153 s = CNEW(u1, COMPILERSTUB_SIZE);
4155 /* set data pointer and code pointer */
4158 s = s + COMPILERSTUB_DATASIZE;
4160 mcodeptr = (s4 *) s;
4162 /* Store the methodinfo* in the same place as in the methodheader
4163 for compiled methods. */
4165 d[0] = (ptrint) asm_call_jit_compiler;
4168 /* code for the stub */
4170 M_ALD(REG_ITMP1, REG_PV, -1 * 8); /* load methodinfo pointer */
4171 M_ALD(REG_PV, REG_PV, -2 * 8); /* load pointer to the compiler */
4172 M_JMP(REG_ZERO, REG_PV); /* jump to the compiler */
4174 #if defined(ENABLE_STATISTICS)
4176 count_cstub_len += COMPILERSTUB_SIZE;
4183 /* createnativestub ************************************************************
4185 Creates a stub routine which calls a native method.
4187 *******************************************************************************/
4189 u1 *createnativestub(functionptr f, methodinfo *m, codegendata *cd,
4190 registerdata *rd, methoddesc *nmd)
4192 s4 *mcodeptr; /* code generation pointer */
4193 s4 stackframesize; /* size of stackframe if needed */
4196 s4 i, j; /* count variables */
4199 s4 funcdisp; /* displacement of the function */
4201 /* initialize variables */
4204 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4207 /* calculate stack frame size */
4210 1 + /* return address */
4211 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4212 sizeof(localref_table) / SIZEOF_VOID_P +
4213 1 + /* methodinfo for call trace */
4214 (md->paramcount > INT_ARG_CNT ? INT_ARG_CNT : md->paramcount) +
4218 /* create method header */
4220 (void) dseg_addaddress(cd, m); /* MethodPointer */
4221 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4222 (void) dseg_adds4(cd, 0); /* IsSync */
4223 (void) dseg_adds4(cd, 0); /* IsLeaf */
4224 (void) dseg_adds4(cd, 0); /* IntSave */
4225 (void) dseg_adds4(cd, 0); /* FltSave */
4226 (void) dseg_addlinenumbertablesize(cd);
4227 (void) dseg_adds4(cd, 0); /* ExTableSize */
4230 /* initialize mcode variables */
4232 mcodeptr = (s4 *) cd->mcodeptr;
4235 /* generate stub code */
4237 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
4238 M_AST(REG_RA, REG_SP, stackframesize * 8 - SIZEOF_VOID_P);
4241 /* call trace function */
4244 /* save integer argument registers */
4246 for (i = 0, j = 1; i < md->paramcount && i < INT_ARG_CNT; i++) {
4247 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4248 M_LST(rd->argintregs[i], REG_SP, j * 8);
4253 /* save and copy float arguments into integer registers */
4255 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4256 t = md->paramtypes[i].type;
4258 if (IS_FLT_DBL_TYPE(t)) {
4259 if (IS_2_WORD_TYPE(t)) {
4260 M_DST(rd->argfltregs[i], REG_SP, j * 8);
4261 M_LLD(rd->argintregs[i], REG_SP, j * 8);
4263 M_FST(rd->argfltregs[i], REG_SP, j * 8);
4264 M_ILD(rd->argintregs[i], REG_SP, j * 8);
4270 disp = dseg_addaddress(cd, m);
4271 M_ALD(REG_ITMP1, REG_PV, disp);
4272 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4273 disp = dseg_addaddress(cd, builtin_trace_args);
4274 M_ALD(REG_PV, REG_PV, disp);
4275 M_JSR(REG_RA, REG_PV);
4276 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4277 M_LDA(REG_PV, REG_RA, -disp);
4279 for (i = 0, j = 1; i < md->paramcount && i < INT_ARG_CNT; i++) {
4280 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4281 M_LLD(rd->argintregs[i], REG_SP, j * 8);
4286 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4287 t = md->paramtypes[i].type;
4289 if (IS_FLT_DBL_TYPE(t)) {
4290 if (IS_2_WORD_TYPE(t)) {
4291 M_DLD(rd->argfltregs[i], REG_SP, j * 8);
4293 M_FLD(rd->argfltregs[i], REG_SP, j * 8);
4300 /* get function address (this must happen before the stackframeinfo) */
4302 funcdisp = dseg_addaddress(cd, f);
4304 #if !defined(WITH_STATIC_CLASSPATH)
4306 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m, funcdisp);
4308 if (opt_showdisassemble)
4313 /* save integer and float argument registers */
4315 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4316 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4317 M_LST(rd->argintregs[i], REG_SP, j * 8);
4322 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4323 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4324 M_DST(rd->argfltregs[i], REG_SP, j * 8);
4329 /* prepare data structures for native function call */
4331 M_LDA(rd->argintregs[0], REG_SP, stackframesize * 8 - SIZEOF_VOID_P);
4332 M_MOV(REG_PV, rd->argintregs[1]);
4333 M_LDA(rd->argintregs[2], REG_SP, stackframesize * 8);
4334 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8 - SIZEOF_VOID_P);
4335 disp = dseg_addaddress(cd, codegen_start_native_call);
4336 M_ALD(REG_PV, REG_PV, disp);
4337 M_JSR(REG_RA, REG_PV);
4338 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4339 M_LDA(REG_PV, REG_RA, -disp);
4341 /* restore integer and float argument registers */
4343 for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
4344 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
4345 M_LLD(rd->argintregs[i], REG_SP, j * 8);
4350 for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
4351 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4352 M_DLD(rd->argfltregs[i], REG_SP, j * 8);
4357 /* copy or spill arguments to new locations */
4359 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4360 t = md->paramtypes[i].type;
4362 if (IS_INT_LNG_TYPE(t)) {
4363 if (!md->params[i].inmemory) {
4364 s1 = rd->argintregs[md->params[i].regoff];
4366 if (!nmd->params[j].inmemory) {
4367 s2 = rd->argintregs[nmd->params[j].regoff];
4371 s2 = nmd->params[j].regoff;
4372 M_LST(s1, REG_SP, s2 * 8);
4376 s1 = md->params[i].regoff + stackframesize;
4377 s2 = nmd->params[j].regoff;
4378 M_LLD(REG_ITMP1, REG_SP, s1 * 8);
4379 M_LST(REG_ITMP1, REG_SP, s2 * 8);
4383 if (!md->params[i].inmemory) {
4384 s1 = rd->argfltregs[md->params[i].regoff];
4386 if (!nmd->params[j].inmemory) {
4387 s2 = rd->argfltregs[nmd->params[j].regoff];
4391 s2 = nmd->params[j].regoff;
4392 if (IS_2_WORD_TYPE(t))
4393 M_DST(s1, REG_SP, s2 * 8);
4395 M_FST(s1, REG_SP, s2 * 8);
4399 s1 = md->params[i].regoff + stackframesize;
4400 s2 = nmd->params[j].regoff;
4401 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4402 if (IS_2_WORD_TYPE(t))
4403 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4405 M_FST(REG_FTMP1, REG_SP, s2 * 8);
4410 /* put class into second argument register */
4412 if (m->flags & ACC_STATIC) {
4413 disp = dseg_addaddress(cd, m->class);
4414 M_ALD(rd->argintregs[1], REG_PV, disp);
4417 /* put env into first argument register */
4419 disp = dseg_addaddress(cd, _Jv_env);
4420 M_ALD(rd->argintregs[0], REG_PV, disp);
4422 /* do the native function call */
4424 M_ALD(REG_PV, REG_PV, funcdisp);
4425 M_JSR(REG_RA, REG_PV); /* call native method */
4426 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4427 M_LDA(REG_PV, REG_RA, -disp); /* recompute pv from ra */
4429 /* save return value */
4431 if (IS_INT_LNG_TYPE(md->returntype.type))
4432 M_LST(REG_RESULT, REG_SP, 0 * 8);
4434 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4436 /* remove native stackframe info */
4438 M_LDA(rd->argintregs[0], REG_SP, stackframesize * 8 - SIZEOF_VOID_P);
4439 disp = dseg_addaddress(cd, codegen_finish_native_call);
4440 M_ALD(REG_PV, REG_PV, disp);
4441 M_JSR(REG_RA, REG_PV);
4442 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4443 M_LDA(REG_PV, REG_RA, -disp);
4445 /* call finished trace */
4448 /* just restore the value we need, don't care about the other */
4450 if (IS_INT_LNG_TYPE(md->returntype.type))
4451 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4453 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4455 disp = dseg_addaddress(cd, m);
4456 M_ALD(rd->argintregs[0], REG_PV, disp);
4458 M_MOV(REG_RESULT, rd->argintregs[1]);
4459 M_FMOV(REG_FRESULT, rd->argfltregs[2]);
4460 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
4462 disp = dseg_addaddress(cd, builtin_displaymethodstop);
4463 M_ALD(REG_PV, REG_PV, disp);
4464 M_JSR(REG_RA, REG_PV);
4465 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4466 M_LDA(REG_PV, REG_RA, -disp);
4469 /* check for exception */
4471 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4472 disp = dseg_addaddress(cd, builtin_get_exceptionptrptr);
4473 M_ALD(REG_PV, REG_PV, disp);
4474 M_JSR(REG_RA, REG_PV);
4475 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
4476 M_LDA(REG_PV, REG_RA, -disp);
4477 M_MOV(REG_RESULT, REG_ITMP3);
4479 disp = dseg_addaddress(cd, &_exceptionptr);
4480 M_ALD(REG_RESULT, REG_PV, disp); /* get address of exceptionptr */
4482 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4484 /* restore return value */
4486 if (IS_INT_LNG_TYPE(md->returntype.type))
4487 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4489 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4491 M_BNEZ(REG_ITMP1, 3); /* if no exception then return */
4493 M_ALD(REG_RA, REG_SP, (stackframesize - 1) * 8); /* load return address */
4494 M_LDA(REG_SP, REG_SP, stackframesize * 8);
4495 M_RET(REG_ZERO, REG_RA); /* return to caller */
4497 /* handle exception */
4499 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4501 M_ALD(REG_RA, REG_SP, (stackframesize - 1) * 8); /* load return address */
4502 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4504 M_LDA(REG_SP, REG_SP, stackframesize * 8);
4506 disp = dseg_addaddress(cd, asm_handle_nat_exception);
4507 M_ALD(REG_ITMP3, REG_PV, disp); /* load asm exception handler address */
4508 M_JMP(REG_ZERO, REG_ITMP3); /* jump to asm exception handler */
4511 /* process patcher calls **************************************************/
4519 /* there can only be one <clinit> ref entry */
4520 pref = cd->patchrefs;
4522 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4523 /* Get machine code which is patched back in later. The call is */
4524 /* 1 instruction word long. */
4526 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4527 mcode = (u4) *xcodeptr;
4529 /* patch in the call to call the following code (done at compile */
4532 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4533 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4535 M_BSR(REG_ITMP3, tmpmcodeptr - (xcodeptr + 1));
4537 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4539 /* create stack frame */
4541 M_LSUB_IMM(REG_SP, 6 * 8, REG_SP);
4543 /* move return address onto stack */
4545 M_AST(REG_ITMP3, REG_SP, 5 * 8);
4547 /* move pointer to java_objectheader onto stack */
4549 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4550 /* create a virtual java_objectheader */
4552 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4553 disp = dseg_addaddress(cd, NULL); /* vftbl */
4555 M_LDA(REG_ITMP3, REG_PV, disp);
4556 M_AST(REG_ITMP3, REG_SP, 4 * 8);
4558 M_AST(REG_ZERO, REG_SP, 4 * 8);
4561 /* move machine code onto stack */
4563 disp = dseg_adds4(cd, mcode);
4564 M_ILD(REG_ITMP3, REG_PV, disp);
4565 M_IST(REG_ITMP3, REG_SP, 3 * 8);
4567 /* move class/method/field reference onto stack */
4569 disp = dseg_addaddress(cd, pref->ref);
4570 M_ALD(REG_ITMP3, REG_PV, disp);
4571 M_AST(REG_ITMP3, REG_SP, 2 * 8);
4573 /* move data segment displacement onto stack */
4575 disp = dseg_adds4(cd, pref->disp);
4576 M_ILD(REG_ITMP3, REG_PV, disp);
4577 M_IST(REG_ITMP3, REG_SP, 1 * 8);
4579 /* move patcher function pointer onto stack */
4581 disp = dseg_addaddress(cd, pref->patcher);
4582 M_ALD(REG_ITMP3, REG_PV, disp);
4583 M_AST(REG_ITMP3, REG_SP, 0 * 8);
4585 disp = dseg_addaddress(cd, asm_wrapper_patcher);
4586 M_ALD(REG_ITMP3, REG_PV, disp);
4587 M_JMP(REG_ZERO, REG_ITMP3);
4591 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4593 return m->entrypoint;
4598 * These are local overrides for various environment variables in Emacs.
4599 * Please do not remove this and leave it at the end of the file, where
4600 * Emacs will automagically detect them.
4601 * ---------------------------------------------------------------------
4604 * indent-tabs-mode: t