1 /* src/vm/jit/mips/codegen.c - machine code generator for MIPS
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
30 Changes: Christian Thalinger
32 Contains the codegenerator for an MIPS (R4000 or higher) processor.
33 This module generates MIPS machine code for a sequence of
34 intermediate code commands (ICMDs).
36 $Id: codegen.c 2297 2005-04-13 12:50:07Z christian $
47 #include "cacao/cacao.h"
48 #include "native/native.h"
49 #include "vm/builtin.h"
50 #include "vm/jit/asmpart.h"
51 #include "vm/jit/jit.h"
53 #include "vm/jit/lsra.h"
55 #include "vm/jit/reg.h"
56 #include "vm/jit/mips/codegen.h"
57 #include "vm/jit/mips/types.h"
60 /* *****************************************************************************
62 Datatypes and Register Allocations:
63 -----------------------------------
65 On 64-bit-machines (like the MIPS) all operands are stored in the
66 registers in a 64-bit form, even when the correspondig JavaVM operands
67 only need 32 bits. This is done by a canonical representation:
69 32-bit integers are allways stored as sign-extended 64-bit values (this
70 approach is directly supported by the MIPS architecture and is very easy
73 32-bit-floats are stored in a 64-bit double precision register by simply
74 expanding the exponent and mantissa with zeroes. (also supported by the
80 The calling conventions and the layout of the stack is explained in detail
81 in the documention file: calling.doc
83 *******************************************************************************/
86 /* register descripton - array ************************************************/
88 /* #define REG_RES 0 reserved register for OS or code generator */
89 /* #define REG_RET 1 return value register */
90 /* #define REG_EXC 2 exception value register (only old jit) */
91 /* #define REG_SAV 3 (callee) saved register */
92 /* #define REG_TMP 4 scratch temporary register (caller saved) */
93 /* #define REG_ARG 5 argument register (caller saved) */
95 /* #define REG_END -1 last entry in tables */
97 static int nregdescint[] = {
98 REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
99 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
100 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
101 REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
104 /* for use of reserved registers, see comment above */
106 static int nregdescfloat[] = {
107 REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
108 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
109 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
110 REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
113 /* for use of reserved registers, see comment above */
116 /* Include independent code generation stuff -- include after register */
117 /* descriptions to avoid extern definitions. */
119 #include "vm/jit/codegen.inc"
120 #include "vm/jit/reg.inc"
122 #include "vm/jit/lsra.inc"
126 /* NullPointerException handlers and exception handling initialisation */
128 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
129 void thread_restartcriticalsection(ucontext_t *uc)
132 if ((critical = thread_checkcritical((void*) uc->uc_mcontext.gregs[CTX_EPC])) != NULL)
133 uc->uc_mcontext.gregs[CTX_EPC] = (u8) critical;
137 /* NullPointerException signal handler for hardware null pointer check */
139 void catch_NullPointerException(int sig, siginfo_t *siginfo, void *_p)
144 java_objectheader *xptr;
146 struct ucontext *_uc = (struct ucontext *) _p;
147 mcontext_t *sigctx = &_uc->uc_mcontext;
148 struct sigaction act;
150 instr = *((s4 *) (sigctx->gregs[CTX_EPC]));
151 faultaddr = sigctx->gregs[(instr >> 21) & 0x1f];
153 if (faultaddr == 0) {
154 /* Reset signal handler - necessary for SysV, does no harm for BSD */
156 act.sa_sigaction = catch_NullPointerException;
157 act.sa_flags = SA_SIGINFO;
158 sigaction(sig, &act, NULL);
161 sigaddset(&nsig, sig);
162 sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
164 xptr = new_nullpointerexception();
166 sigctx->gregs[REG_ITMP1_XPTR] = (u8) xptr;
167 sigctx->gregs[REG_ITMP2_XPC] = sigctx->gregs[CTX_EPC];
168 sigctx->gregs[CTX_EPC] = (u8) asm_handle_exception;
171 faultaddr += (long) ((instr << 16) >> 16);
172 fprintf(stderr, "faulting address: 0x%lx at 0x%lx\n", (long) faultaddr, (long) sigctx->gregs[CTX_EPC]);
173 panic("Stack overflow");
180 void init_exceptions(void)
182 struct sigaction act;
184 /* The Boehm GC initialization blocks the SIGSEGV signal. So we do a
185 dummy allocation here to ensure that the GC is initialized.
187 heap_allocate(1, 0, NULL);
189 /* install signal handlers we need to convert to exceptions */
191 sigemptyset(&act.sa_mask);
194 act.sa_sigaction = catch_NullPointerException;
195 act.sa_flags = SA_SIGINFO;
198 sigaction(SIGSEGV, &act, NULL);
202 sigaction(SIGBUS, &act, NULL);
206 /* Turn off flush-to-zero */
209 n.fc_word = get_fpc_csr();
210 n.fc_struct.flush = 0;
211 set_fpc_csr(n.fc_word);
216 /* function gen_mcode **********************************************************
218 generates machine code
220 *******************************************************************************/
222 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
224 s4 len, s1, s2, s3, d;
238 savedregs_num = (m->isleafmethod) ? 0 : 1; /* space to save the RA */
240 /* space to save used callee saved registers */
242 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
243 savedregs_num += (rd->savfltregcnt - rd->maxsavfltreguse);
245 parentargs_base = rd->maxmemuse + savedregs_num;
247 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
249 if (checksync && (m->flags & ACC_SYNCHRONIZED))
254 /* adjust frame size for 16 byte alignment */
256 if (parentargs_base & 1)
259 /* create method header */
262 (void) dseg_addaddress(cd, m); /* Filler */
264 (void) dseg_addaddress(cd, m); /* MethodPointer */
265 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
267 #if defined(USE_THREADS)
269 /* IsSync contains the offset relative to the stack pointer for the
270 argument of monitor_exit used in the exception handler. Since the
271 offset could be zero and give a wrong meaning of the flag it is
275 if (checksync && (m->flags & ACC_SYNCHRONIZED))
276 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 8); /* IsSync */
281 (void) dseg_adds4(cd, 0); /* IsSync */
283 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
284 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse);/* IntSave */
285 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse);/* FltSave */
286 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
288 /* create exception table */
290 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
291 dseg_addtarget(cd, ex->start);
292 dseg_addtarget(cd, ex->end);
293 dseg_addtarget(cd, ex->handler);
294 (void) dseg_addaddress(cd, ex->catchtype.cls);
297 /* initialize mcode variables */
299 mcodeptr = (s4 *) cd->mcodebase;
300 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
301 MCODECHECK(128 + m->paramcount);
303 /* create stack frame (if necessary) */
305 if (parentargs_base) {
306 M_LDA(REG_SP, REG_SP, -parentargs_base * 8);
309 /* save return address and used callee saved registers */
312 if (!m->isleafmethod) {
313 p--; M_LST(REG_RA, REG_SP, 8 * p);
315 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
316 p--; M_LST(rd->savintregs[i], REG_SP, 8 * p);
318 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
319 p--; M_DST(rd->savfltregs[i], REG_SP, 8 * p);
322 /* save monitorenter argument */
324 #if defined(USE_THREADS)
325 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
326 if (m->flags & ACC_STATIC) {
327 p = dseg_addaddress(cd, m->class);
328 M_ALD(REG_ITMP1, REG_PV, p);
329 M_AST(REG_ITMP1, REG_SP, rd->maxmemuse * 8);
332 M_AST(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
337 /* copy argument registers to stack and call trace function with pointer
338 to arguments on stack. ToDo: save floating point registers !!!!!!!!!
342 M_LDA(REG_SP, REG_SP, -(18 * 8));
343 M_LST(REG_RA, REG_SP, 1 * 8);
345 /* save integer argument registers */
346 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
347 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
350 /* save and copy float arguments into integer registers */
351 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
352 t = m->paramtypes[p];
354 if (IS_FLT_DBL_TYPE(t)) {
355 if (IS_2_WORD_TYPE(t)) {
356 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
357 M_LLD(rd->argintregs[p], REG_SP, (10 + p) * 8);
360 M_FST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
361 M_ILD(rd->argintregs[p], REG_SP, (10 + p) * 8);
365 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
369 p = dseg_addaddress(cd, m);
370 M_ALD(REG_ITMP1, REG_PV, p);
371 M_LST(REG_ITMP1, REG_SP, 0);
372 p = dseg_addaddress(cd, (void *) builtin_trace_args);
373 M_ALD(REG_ITMP3, REG_PV, p);
374 M_JSR(REG_RA, REG_ITMP3);
377 M_LLD(REG_RA, REG_SP, 1 * 8);
379 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
380 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
383 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
384 t = m->paramtypes[p];
386 if (IS_FLT_DBL_TYPE(t)) {
387 if (IS_2_WORD_TYPE(t)) {
388 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
391 M_FLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
395 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
399 M_LDA(REG_SP, REG_SP, 18 * 8);
402 /* take arguments out of register or stack frame */
404 for (p = 0, l = 0; p < m->paramcount; p++) {
405 t = m->paramtypes[p];
406 var = &(rd->locals[l][t]);
408 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
412 if (IS_INT_LNG_TYPE(t)) { /* integer args */
413 if (p < INT_ARG_CNT) { /* register arguments */
414 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
415 M_INTMOVE(rd->argintregs[p], var->regoff);
416 } else { /* reg arg -> spilled */
417 M_LST(rd->argintregs[p], REG_SP, 8 * var->regoff);
420 } else { /* stack arguments */
421 pa = p - INT_ARG_CNT;
422 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
423 M_LLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
425 } else { /* stack arg -> spilled */
426 /* M_LLD(REG_ITMP1, REG_SP, 8 * (parentargs_base + pa)); */
427 /* M_LST(REG_ITMP1, REG_SP, 8 * var->regoff); */
428 var->regoff = parentargs_base + pa;
432 } else { /* floating args */
433 if (p < FLT_ARG_CNT) { /* register arguments */
434 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
435 M_TFLTMOVE(var->type, rd->argfltregs[p], var->regoff);
437 } else { /* reg arg -> spilled */
438 M_DST(rd->argfltregs[p], REG_SP, var->regoff * 8);
441 } else { /* stack arguments */
442 pa = p - FLT_ARG_CNT;
443 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
444 M_DLD(var->regoff, REG_SP, 8 * (parentargs_base + pa));
446 } else { /* stack-arg -> spilled */
447 /* M_DLD(REG_FTMP1, REG_SP, 8 * (parentargs_base + pa)); */
448 /* M_DST(REG_FTMP1, REG_SP, 8 * var->regoff); */
449 var->regoff = parentargs_base + pa;
455 /* call monitorenter function */
457 #if defined(USE_THREADS)
458 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
460 s8 func_enter = (m->flags & ACC_STATIC) ?
461 (s8) builtin_staticmonitorenter : (s8) builtin_monitorenter;
462 p = dseg_addaddress(cd, (void *) func_enter);
463 M_ALD(REG_ITMP3, REG_PV, p);
464 M_JSR(REG_RA, REG_ITMP3);
465 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
466 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
467 M_LDA(REG_PV, REG_RA, disp);
472 /* end of header generation */
474 /* walk through all basic blocks */
475 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
477 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
479 if (bptr->flags >= BBREACHED) {
481 /* branch resolving */
484 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
485 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
491 /* copy interface registers to their destination */
498 while (src != NULL) {
500 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
501 /* d = reg_of_var(m, src, REG_ITMP1); */
502 if (!(src->flags & INMEMORY))
506 M_INTMOVE(REG_ITMP1, d);
507 store_reg_to_var_int(src, d);
513 while (src != NULL) {
515 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
516 d = reg_of_var(rd, src, REG_ITMP1);
517 M_INTMOVE(REG_ITMP1, d);
518 store_reg_to_var_int(src, d);
521 d = reg_of_var(rd, src, REG_IFTMP);
522 if ((src->varkind != STACKVAR)) {
524 if (IS_FLT_DBL_TYPE(s2)) {
525 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
526 s1 = rd->interfaces[len][s2].regoff;
527 M_TFLTMOVE(s2, s1, d);
530 M_DLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
532 store_reg_to_var_flt(src, d);
535 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
536 s1 = rd->interfaces[len][s2].regoff;
540 M_LLD(d, REG_SP, 8 * rd->interfaces[len][s2].regoff);
542 store_reg_to_var_int(src, d);
551 /* walk through all instructions */
555 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
557 MCODECHECK(64); /* an instruction usually needs < 64 words */
560 case ICMD_NOP: /* ... ==> ... */
563 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
565 var_to_reg_int(s1, src, REG_ITMP1);
567 codegen_addxnullrefs(cd, mcodeptr);
571 /* constant operations ************************************************/
573 case ICMD_ICONST: /* ... ==> ..., constant */
574 /* op1 = 0, val.i = constant */
576 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
577 ICONST(d, iptr->val.i);
578 store_reg_to_var_int(iptr->dst, d);
581 case ICMD_LCONST: /* ... ==> ..., constant */
582 /* op1 = 0, val.l = constant */
584 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
585 LCONST(d, iptr->val.l);
586 store_reg_to_var_int(iptr->dst, d);
589 case ICMD_FCONST: /* ... ==> ..., constant */
590 /* op1 = 0, val.f = constant */
592 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
593 a = dseg_addfloat(cd, iptr->val.f);
595 store_reg_to_var_flt(iptr->dst, d);
598 case ICMD_DCONST: /* ... ==> ..., constant */
599 /* op1 = 0, val.d = constant */
601 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
602 a = dseg_adddouble(cd, iptr->val.d);
604 store_reg_to_var_flt (iptr->dst, d);
607 case ICMD_ACONST: /* ... ==> ..., constant */
608 /* op1 = 0, val.a = constant */
610 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
612 a = dseg_addaddress(cd, iptr->val.a);
615 M_INTMOVE(REG_ZERO, d);
617 store_reg_to_var_int(iptr->dst, d);
621 /* load/store operations **********************************************/
623 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
624 case ICMD_LLOAD: /* op1 = local variable */
627 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
628 if ((iptr->dst->varkind == LOCALVAR) &&
629 (iptr->dst->varnum == iptr->op1))
631 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
632 if (var->flags & INMEMORY) {
633 M_LLD(d, REG_SP, 8 * var->regoff);
635 M_INTMOVE(var->regoff,d);
637 store_reg_to_var_int(iptr->dst, d);
640 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
641 case ICMD_DLOAD: /* op1 = local variable */
643 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
644 if ((iptr->dst->varkind == LOCALVAR) &&
645 (iptr->dst->varnum == iptr->op1))
647 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
649 int t2 = ((iptr->opc == ICMD_FLOAD) ? TYPE_FLT : TYPE_DBL);
650 if (var->flags & INMEMORY) {
651 M_CCFLD(var->type, t2, d, REG_SP, 8 * var->regoff);
653 M_CCFLTMOVE(var->type, t2, var->regoff, d);
656 store_reg_to_var_flt(iptr->dst, d);
660 case ICMD_ISTORE: /* ..., value ==> ... */
661 case ICMD_LSTORE: /* op1 = local variable */
664 if ((src->varkind == LOCALVAR) &&
665 (src->varnum == iptr->op1))
667 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
668 if (var->flags & INMEMORY) {
669 var_to_reg_int(s1, src, REG_ITMP1);
670 M_LST(s1, REG_SP, 8 * var->regoff);
673 var_to_reg_int(s1, src, var->regoff);
674 M_INTMOVE(s1, var->regoff);
678 case ICMD_FSTORE: /* ..., value ==> ... */
679 case ICMD_DSTORE: /* op1 = local variable */
681 if ((src->varkind == LOCALVAR) &&
682 (src->varnum == iptr->op1))
684 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
686 int t1 = ((iptr->opc == ICMD_FSTORE) ? TYPE_FLT : TYPE_DBL);
687 if (var->flags & INMEMORY) {
688 var_to_reg_flt(s1, src, REG_FTMP1);
689 M_CCFST(t1, var->type, s1, REG_SP, 8 * var->regoff);
692 var_to_reg_flt(s1, src, var->regoff);
693 M_CCFLTMOVE(t1, var->type, s1, var->regoff);
699 /* pop/dup/swap operations ********************************************/
701 /* attention: double and longs are only one entry in CACAO ICMDs */
703 case ICMD_POP: /* ..., value ==> ... */
704 case ICMD_POP2: /* ..., value, value ==> ... */
707 case ICMD_DUP: /* ..., a ==> ..., a, a */
708 M_COPY(src, iptr->dst);
711 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
713 M_COPY(src, iptr->dst);
714 M_COPY(src->prev, iptr->dst->prev);
715 M_COPY(iptr->dst, iptr->dst->prev->prev);
718 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
720 M_COPY(src, iptr->dst);
721 M_COPY(src->prev, iptr->dst->prev);
722 M_COPY(src->prev->prev, iptr->dst->prev->prev);
723 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
726 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
728 M_COPY(src, iptr->dst);
729 M_COPY(src->prev, iptr->dst->prev);
732 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
734 M_COPY(src, iptr->dst);
735 M_COPY(src->prev, iptr->dst->prev);
736 M_COPY(src->prev->prev, iptr->dst->prev->prev);
737 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
738 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
741 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
743 M_COPY(src, iptr->dst);
744 M_COPY(src->prev, iptr->dst->prev);
745 M_COPY(src->prev->prev, iptr->dst->prev->prev);
746 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
747 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
748 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
751 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
753 M_COPY(src, iptr->dst->prev);
754 M_COPY(src->prev, iptr->dst);
758 /* integer operations *************************************************/
760 case ICMD_INEG: /* ..., value ==> ..., - value */
762 var_to_reg_int(s1, src, REG_ITMP1);
763 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
764 M_ISUB(REG_ZERO, s1, d);
765 store_reg_to_var_int(iptr->dst, d);
768 case ICMD_LNEG: /* ..., value ==> ..., - value */
770 var_to_reg_int(s1, src, REG_ITMP1);
771 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
772 M_LSUB(REG_ZERO, s1, d);
773 store_reg_to_var_int(iptr->dst, d);
776 case ICMD_I2L: /* ..., value ==> ..., value */
778 var_to_reg_int(s1, src, REG_ITMP1);
779 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
781 store_reg_to_var_int(iptr->dst, d);
784 case ICMD_L2I: /* ..., value ==> ..., value */
786 var_to_reg_int(s1, src, REG_ITMP1);
787 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
788 M_ISLL_IMM(s1, 0, d );
789 store_reg_to_var_int(iptr->dst, d);
792 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
794 var_to_reg_int(s1, src, REG_ITMP1);
795 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
796 M_LSLL_IMM(s1, 56, d);
797 M_LSRA_IMM( d, 56, d);
798 store_reg_to_var_int(iptr->dst, d);
801 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
803 var_to_reg_int(s1, src, REG_ITMP1);
804 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
806 store_reg_to_var_int(iptr->dst, d);
809 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
811 var_to_reg_int(s1, src, REG_ITMP1);
812 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
813 M_LSLL_IMM(s1, 48, d);
814 M_LSRA_IMM( d, 48, d);
815 store_reg_to_var_int(iptr->dst, d);
819 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
821 var_to_reg_int(s1, src->prev, REG_ITMP1);
822 var_to_reg_int(s2, src, REG_ITMP2);
823 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
825 store_reg_to_var_int(iptr->dst, d);
828 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
829 /* val.i = constant */
831 var_to_reg_int(s1, src, REG_ITMP1);
832 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
833 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
834 M_IADD_IMM(s1, iptr->val.i, d);
837 ICONST(REG_ITMP2, iptr->val.i);
838 M_IADD(s1, REG_ITMP2, d);
840 store_reg_to_var_int(iptr->dst, d);
843 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
845 var_to_reg_int(s1, src->prev, REG_ITMP1);
846 var_to_reg_int(s2, src, REG_ITMP2);
847 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
849 store_reg_to_var_int(iptr->dst, d);
852 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
853 /* val.l = constant */
855 var_to_reg_int(s1, src, REG_ITMP1);
856 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
857 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
858 M_LADD_IMM(s1, iptr->val.l, d);
861 LCONST(REG_ITMP2, iptr->val.l);
862 M_LADD(s1, REG_ITMP2, d);
864 store_reg_to_var_int(iptr->dst, d);
867 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
869 var_to_reg_int(s1, src->prev, REG_ITMP1);
870 var_to_reg_int(s2, src, REG_ITMP2);
871 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
873 store_reg_to_var_int(iptr->dst, d);
876 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
877 /* val.i = constant */
879 var_to_reg_int(s1, src, REG_ITMP1);
880 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
881 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
882 M_IADD_IMM(s1, -iptr->val.i, d);
885 ICONST(REG_ITMP2, iptr->val.i);
886 M_ISUB(s1, REG_ITMP2, d);
888 store_reg_to_var_int(iptr->dst, d);
891 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
893 var_to_reg_int(s1, src->prev, REG_ITMP1);
894 var_to_reg_int(s2, src, REG_ITMP2);
895 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
897 store_reg_to_var_int(iptr->dst, d);
900 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
901 /* val.l = constant */
903 var_to_reg_int(s1, src, REG_ITMP1);
904 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
905 if ((iptr->val.l >= -32767) && (iptr->val.l <= 32768)) {
906 M_LADD_IMM(s1, -iptr->val.l, d);
909 LCONST(REG_ITMP2, iptr->val.l);
910 M_LSUB(s1, REG_ITMP2, d);
912 store_reg_to_var_int(iptr->dst, d);
915 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
917 var_to_reg_int(s1, src->prev, REG_ITMP1);
918 var_to_reg_int(s2, src, REG_ITMP2);
919 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
924 store_reg_to_var_int(iptr->dst, d);
927 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
928 /* val.i = constant */
930 var_to_reg_int(s1, src, REG_ITMP1);
931 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
932 ICONST(REG_ITMP2, iptr->val.i);
933 M_IMUL(s1, REG_ITMP2);
937 store_reg_to_var_int(iptr->dst, d);
940 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
942 var_to_reg_int(s1, src->prev, REG_ITMP1);
943 var_to_reg_int(s2, src, REG_ITMP2);
944 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
949 store_reg_to_var_int(iptr->dst, d);
952 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
953 /* val.l = constant */
955 var_to_reg_int(s1, src, REG_ITMP1);
956 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
957 LCONST(REG_ITMP2, iptr->val.l);
958 M_LMUL(s1, REG_ITMP2);
962 store_reg_to_var_int(iptr->dst, d);
965 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
967 var_to_reg_int(s1, src->prev, REG_ITMP1);
968 var_to_reg_int(s2, src, REG_ITMP2);
969 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
974 store_reg_to_var_int(iptr->dst, d);
977 case ICMD_IDIVCONST: /* ..., value ==> ..., value / constant */
978 /* val.i = constant */
980 var_to_reg_int(s1, src, REG_ITMP1);
981 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
982 ICONST(REG_ITMP2, iptr->val.i);
983 M_IDIV(s1, REG_ITMP2);
987 store_reg_to_var_int(iptr->dst, d);
990 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
992 var_to_reg_int(s1, src->prev, REG_ITMP1);
993 var_to_reg_int(s2, src, REG_ITMP2);
994 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
999 store_reg_to_var_int(iptr->dst, d);
1002 case ICMD_LDIVCONST: /* ..., value ==> ..., value / constant */
1003 /* val.l = constant */
1005 var_to_reg_int(s1, src, REG_ITMP1);
1006 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1007 LCONST(REG_ITMP2, iptr->val.l);
1008 M_LDIV(s1, REG_ITMP2);
1012 store_reg_to_var_int(iptr->dst, d);
1015 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1017 var_to_reg_int(s1, src->prev, REG_ITMP1);
1018 var_to_reg_int(s2, src, REG_ITMP2);
1019 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1024 store_reg_to_var_int(iptr->dst, d);
1027 case ICMD_IREMCONST: /* ..., value ==> ..., value % constant */
1028 /* val.i = constant */
1030 var_to_reg_int(s1, src, REG_ITMP1);
1031 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1032 ICONST(REG_ITMP2, iptr->val.i);
1033 M_IDIV(s1, REG_ITMP2);
1037 store_reg_to_var_int(iptr->dst, d);
1040 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1042 var_to_reg_int(s1, src->prev, REG_ITMP1);
1043 var_to_reg_int(s2, src, REG_ITMP2);
1044 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1049 store_reg_to_var_int(iptr->dst, d);
1052 case ICMD_LREMCONST: /* ..., value ==> ..., value % constant */
1053 /* val.l = constant */
1055 var_to_reg_int(s1, src, REG_ITMP1);
1056 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1057 LCONST(REG_ITMP2, iptr->val.l);
1058 M_LDIV(s1, REG_ITMP2);
1062 store_reg_to_var_int(iptr->dst, d);
1065 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1066 case ICMD_LDIVPOW2: /* val.i = constant */
1068 var_to_reg_int(s1, src, REG_ITMP1);
1069 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1070 M_LSRA_IMM(s1, 63, REG_ITMP2);
1071 M_LSRL_IMM(REG_ITMP2, 64 - iptr->val.i, REG_ITMP2);
1072 M_LADD(s1, REG_ITMP2, REG_ITMP2);
1073 M_LSRA_IMM(REG_ITMP2, iptr->val.i, d);
1074 store_reg_to_var_int(iptr->dst, d);
1077 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1079 var_to_reg_int(s1, src->prev, REG_ITMP1);
1080 var_to_reg_int(s2, src, REG_ITMP2);
1081 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1083 store_reg_to_var_int(iptr->dst, d);
1086 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1087 /* val.i = constant */
1089 var_to_reg_int(s1, src, REG_ITMP1);
1090 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1091 M_ISLL_IMM(s1, iptr->val.i, d);
1092 store_reg_to_var_int(iptr->dst, d);
1095 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1097 var_to_reg_int(s1, src->prev, REG_ITMP1);
1098 var_to_reg_int(s2, src, REG_ITMP2);
1099 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1101 store_reg_to_var_int(iptr->dst, d);
1104 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1105 /* val.i = constant */
1107 var_to_reg_int(s1, src, REG_ITMP1);
1108 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1109 M_ISRA_IMM(s1, iptr->val.i, d);
1110 store_reg_to_var_int(iptr->dst, d);
1113 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1115 var_to_reg_int(s1, src->prev, REG_ITMP1);
1116 var_to_reg_int(s2, src, REG_ITMP2);
1117 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1119 store_reg_to_var_int(iptr->dst, d);
1122 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1123 /* val.i = constant */
1125 var_to_reg_int(s1, src, REG_ITMP1);
1126 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1127 M_ISRL_IMM(s1, iptr->val.i, d);
1128 store_reg_to_var_int(iptr->dst, d);
1131 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1133 var_to_reg_int(s1, src->prev, REG_ITMP1);
1134 var_to_reg_int(s2, src, REG_ITMP2);
1135 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1137 store_reg_to_var_int(iptr->dst, d);
1140 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1141 /* val.i = constant */
1143 var_to_reg_int(s1, src, REG_ITMP1);
1144 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1145 M_LSLL_IMM(s1, iptr->val.i, d);
1146 store_reg_to_var_int(iptr->dst, d);
1149 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1151 var_to_reg_int(s1, src->prev, REG_ITMP1);
1152 var_to_reg_int(s2, src, REG_ITMP2);
1153 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1155 store_reg_to_var_int(iptr->dst, d);
1158 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1159 /* val.i = constant */
1161 var_to_reg_int(s1, src, REG_ITMP1);
1162 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1163 M_LSRA_IMM(s1, iptr->val.i, d);
1164 store_reg_to_var_int(iptr->dst, d);
1167 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1169 var_to_reg_int(s1, src->prev, REG_ITMP1);
1170 var_to_reg_int(s2, src, REG_ITMP2);
1171 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1173 store_reg_to_var_int(iptr->dst, d);
1176 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1177 /* val.i = constant */
1179 var_to_reg_int(s1, src, REG_ITMP1);
1180 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1181 M_LSRL_IMM(s1, iptr->val.i, d);
1182 store_reg_to_var_int(iptr->dst, d);
1185 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1188 var_to_reg_int(s1, src->prev, REG_ITMP1);
1189 var_to_reg_int(s2, src, REG_ITMP2);
1190 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1192 store_reg_to_var_int(iptr->dst, d);
1195 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1196 /* val.i = constant */
1198 var_to_reg_int(s1, src, REG_ITMP1);
1199 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1200 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1201 M_AND_IMM(s1, iptr->val.i, d);
1204 ICONST(REG_ITMP2, iptr->val.i);
1205 M_AND(s1, REG_ITMP2, d);
1207 store_reg_to_var_int(iptr->dst, d);
1210 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1211 /* val.i = constant */
1213 var_to_reg_int(s1, src, REG_ITMP1);
1214 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1216 M_MOV(s1, REG_ITMP1);
1219 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1220 M_AND_IMM(s1, iptr->val.i, d);
1223 M_ISUB(REG_ZERO, s1, d);
1224 M_AND_IMM(d, iptr->val.i, d);
1227 ICONST(REG_ITMP2, iptr->val.i);
1228 M_AND(s1, REG_ITMP2, d);
1231 M_ISUB(REG_ZERO, s1, d);
1232 M_AND(d, REG_ITMP2, d);
1234 M_ISUB(REG_ZERO, d, d);
1235 store_reg_to_var_int(iptr->dst, d);
1238 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1239 /* val.l = constant */
1241 var_to_reg_int(s1, src, REG_ITMP1);
1242 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1243 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1244 M_AND_IMM(s1, iptr->val.l, d);
1247 LCONST(REG_ITMP2, iptr->val.l);
1248 M_AND(s1, REG_ITMP2, d);
1250 store_reg_to_var_int(iptr->dst, d);
1253 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1254 /* val.l = constant */
1256 var_to_reg_int(s1, src, REG_ITMP1);
1257 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1259 M_MOV(s1, REG_ITMP1);
1262 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1263 M_AND_IMM(s1, iptr->val.l, d);
1266 M_LSUB(REG_ZERO, s1, d);
1267 M_AND_IMM(d, iptr->val.l, d);
1270 LCONST(REG_ITMP2, iptr->val.l);
1271 M_AND(s1, REG_ITMP2, d);
1274 M_LSUB(REG_ZERO, s1, d);
1275 M_AND(d, REG_ITMP2, d);
1277 M_LSUB(REG_ZERO, d, d);
1278 store_reg_to_var_int(iptr->dst, d);
1281 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1284 var_to_reg_int(s1, src->prev, REG_ITMP1);
1285 var_to_reg_int(s2, src, REG_ITMP2);
1286 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1288 store_reg_to_var_int(iptr->dst, d);
1291 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1292 /* val.i = constant */
1294 var_to_reg_int(s1, src, REG_ITMP1);
1295 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1296 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1297 M_OR_IMM(s1, iptr->val.i, d);
1300 ICONST(REG_ITMP2, iptr->val.i);
1301 M_OR(s1, REG_ITMP2, d);
1303 store_reg_to_var_int(iptr->dst, d);
1306 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1307 /* val.l = constant */
1309 var_to_reg_int(s1, src, REG_ITMP1);
1310 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1311 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1312 M_OR_IMM(s1, iptr->val.l, d);
1315 LCONST(REG_ITMP2, iptr->val.l);
1316 M_OR(s1, REG_ITMP2, d);
1318 store_reg_to_var_int(iptr->dst, d);
1321 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1324 var_to_reg_int(s1, src->prev, REG_ITMP1);
1325 var_to_reg_int(s2, src, REG_ITMP2);
1326 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1328 store_reg_to_var_int(iptr->dst, d);
1331 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1332 /* val.i = constant */
1334 var_to_reg_int(s1, src, REG_ITMP1);
1335 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1336 if ((iptr->val.i >= 0) && (iptr->val.i <= 0xffff)) {
1337 M_XOR_IMM(s1, iptr->val.i, d);
1340 ICONST(REG_ITMP2, iptr->val.i);
1341 M_XOR(s1, REG_ITMP2, d);
1343 store_reg_to_var_int(iptr->dst, d);
1346 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1347 /* val.l = constant */
1349 var_to_reg_int(s1, src, REG_ITMP1);
1350 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1351 if ((iptr->val.l >= 0) && (iptr->val.l <= 0xffff)) {
1352 M_XOR_IMM(s1, iptr->val.l, d);
1355 LCONST(REG_ITMP2, iptr->val.l);
1356 M_XOR(s1, REG_ITMP2, d);
1358 store_reg_to_var_int(iptr->dst, d);
1362 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1364 var_to_reg_int(s1, src->prev, REG_ITMP1);
1365 var_to_reg_int(s2, src, REG_ITMP2);
1366 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1367 M_CMPLT(s1, s2, REG_ITMP3);
1368 M_CMPLT(s2, s1, REG_ITMP1);
1369 M_LSUB (REG_ITMP1, REG_ITMP3, d);
1370 store_reg_to_var_int(iptr->dst, d);
1374 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1375 /* op1 = variable, val.i = constant */
1377 var = &(rd->locals[iptr->op1][TYPE_INT]);
1378 if (var->flags & INMEMORY) {
1380 M_LLD(s1, REG_SP, 8 * var->regoff);
1384 M_IADD_IMM(s1, iptr->val.i, s1);
1385 if (var->flags & INMEMORY)
1386 M_LST(s1, REG_SP, 8 * var->regoff);
1390 /* floating operations ************************************************/
1392 case ICMD_FNEG: /* ..., value ==> ..., - value */
1394 var_to_reg_flt(s1, src, REG_FTMP1);
1395 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1397 store_reg_to_var_flt(iptr->dst, d);
1400 case ICMD_DNEG: /* ..., value ==> ..., - value */
1402 var_to_reg_flt(s1, src, REG_FTMP1);
1403 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1405 store_reg_to_var_flt(iptr->dst, d);
1408 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1410 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1411 var_to_reg_flt(s2, src, REG_FTMP2);
1412 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1414 store_reg_to_var_flt(iptr->dst, d);
1417 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1419 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1420 var_to_reg_flt(s2, src, REG_FTMP2);
1421 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1423 store_reg_to_var_flt(iptr->dst, d);
1426 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1428 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1429 var_to_reg_flt(s2, src, REG_FTMP2);
1430 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1432 store_reg_to_var_flt(iptr->dst, d);
1435 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1437 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1438 var_to_reg_flt(s2, src, REG_FTMP2);
1439 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1441 store_reg_to_var_flt(iptr->dst, d);
1444 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1446 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1447 var_to_reg_flt(s2, src, REG_FTMP2);
1448 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1450 store_reg_to_var_flt(iptr->dst, d);
1453 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1455 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1456 var_to_reg_flt(s2, src, REG_FTMP2);
1457 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1459 store_reg_to_var_flt(iptr->dst, d);
1462 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1464 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1465 var_to_reg_flt(s2, src, REG_FTMP2);
1466 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1468 store_reg_to_var_flt(iptr->dst, d);
1471 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1473 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1474 var_to_reg_flt(s2, src, REG_FTMP2);
1475 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1477 store_reg_to_var_flt(iptr->dst, d);
1480 case ICMD_FREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1483 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1484 var_to_reg_flt(s2, src, REG_FTMP2);
1485 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1486 M_FDIV(s1,s2, REG_FTMP3);
1487 M_FLOORFL(REG_FTMP3, REG_FTMP3);
1488 M_CVTLF(REG_FTMP3, REG_FTMP3);
1489 M_FMUL(REG_FTMP3, s2, REG_FTMP3);
1490 M_FSUB(s1, REG_FTMP3, d);
1491 store_reg_to_var_flt(iptr->dst, d);
1494 case ICMD_DREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1496 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1497 var_to_reg_flt(s2, src, REG_FTMP2);
1498 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1499 M_DDIV(s1,s2, REG_FTMP3);
1500 M_FLOORDL(REG_FTMP3, REG_FTMP3);
1501 M_CVTLD(REG_FTMP3, REG_FTMP3);
1502 M_DMUL(REG_FTMP3, s2, REG_FTMP3);
1503 M_DSUB(s1, REG_FTMP3, d);
1504 store_reg_to_var_flt(iptr->dst, d);
1507 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1509 var_to_reg_int(s1, src, REG_ITMP1);
1510 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1513 store_reg_to_var_flt(iptr->dst, d);
1516 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1518 var_to_reg_int(s1, src, REG_ITMP1);
1519 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1522 store_reg_to_var_flt(iptr->dst, d);
1525 case ICMD_F2I: /* ..., (float) value ==> ..., (int) value */
1527 var_to_reg_flt(s1, src, REG_FTMP1);
1528 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1529 M_TRUNCFI(s1, REG_FTMP1);
1530 M_MOVDI(REG_FTMP1, d);
1532 store_reg_to_var_int(iptr->dst, d);
1535 case ICMD_D2I: /* ..., (double) value ==> ..., (int) value */
1537 var_to_reg_flt(s1, src, REG_FTMP1);
1538 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1539 M_TRUNCDI(s1, REG_FTMP1);
1540 M_MOVDI(REG_FTMP1, d);
1542 store_reg_to_var_int(iptr->dst, d);
1545 case ICMD_F2L: /* ..., (float) value ==> ..., (long) value */
1547 var_to_reg_flt(s1, src, REG_FTMP1);
1548 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1549 M_TRUNCFL(s1, REG_FTMP1);
1550 M_MOVDL(REG_FTMP1, d);
1552 store_reg_to_var_int(iptr->dst, d);
1555 case ICMD_D2L: /* ..., (double) value ==> ..., (long) value */
1557 var_to_reg_flt(s1, src, REG_FTMP1);
1558 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1559 M_TRUNCDL(s1, REG_FTMP1);
1560 M_MOVDL(REG_FTMP1, d);
1562 store_reg_to_var_int(iptr->dst, d);
1565 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1567 var_to_reg_flt(s1, src, REG_FTMP1);
1568 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1570 store_reg_to_var_flt(iptr->dst, d);
1573 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1575 var_to_reg_flt(s1, src, REG_FTMP1);
1576 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1578 store_reg_to_var_flt(iptr->dst, d);
1581 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1583 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1584 var_to_reg_flt(s2, src, REG_FTMP2);
1585 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1588 M_LADD_IMM(REG_ZERO, 1, d);
1592 M_LSUB_IMM(REG_ZERO, 1, d);
1593 M_CMOVT(REG_ZERO, d);
1594 store_reg_to_var_int(iptr->dst, d);
1597 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1599 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1600 var_to_reg_flt(s2, src, REG_FTMP2);
1601 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1604 M_LADD_IMM(REG_ZERO, 1, d);
1608 M_LSUB_IMM(REG_ZERO, 1, d);
1609 M_CMOVT(REG_ZERO, d);
1610 store_reg_to_var_int(iptr->dst, d);
1613 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1615 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1616 var_to_reg_flt(s2, src, REG_FTMP2);
1617 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1620 M_LSUB_IMM(REG_ZERO, 1, d);
1624 M_LADD_IMM(REG_ZERO, 1, d);
1625 M_CMOVT(REG_ZERO, d);
1626 store_reg_to_var_int(iptr->dst, d);
1629 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1631 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1632 var_to_reg_flt(s2, src, REG_FTMP2);
1633 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1636 M_LSUB_IMM(REG_ZERO, 1, d);
1640 M_LADD_IMM(REG_ZERO, 1, d);
1641 M_CMOVT(REG_ZERO, d);
1642 store_reg_to_var_int(iptr->dst, d);
1646 /* memory operations **************************************************/
1648 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1650 var_to_reg_int(s1, src, REG_ITMP1);
1651 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1652 gen_nullptr_check(s1);
1653 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1654 store_reg_to_var_int(iptr->dst, d);
1657 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1659 var_to_reg_int(s1, src->prev, REG_ITMP1);
1660 var_to_reg_int(s2, src, REG_ITMP2);
1661 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1662 if (iptr->op1 == 0) {
1663 gen_nullptr_check(s1);
1666 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1667 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1668 M_ALD(d, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1669 store_reg_to_var_int(iptr->dst, d);
1672 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1674 var_to_reg_int(s1, src->prev, REG_ITMP1);
1675 var_to_reg_int(s2, src, REG_ITMP2);
1676 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1677 if (iptr->op1 == 0) {
1678 gen_nullptr_check(s1);
1681 M_ASLL_IMM(s2, 2, REG_ITMP2);
1682 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1683 M_ILD(d, REG_ITMP1, OFFSET(java_intarray, data[0]));
1684 store_reg_to_var_int(iptr->dst, d);
1687 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1689 var_to_reg_int(s1, src->prev, REG_ITMP1);
1690 var_to_reg_int(s2, src, REG_ITMP2);
1691 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1692 if (iptr->op1 == 0) {
1693 gen_nullptr_check(s1);
1696 M_ASLL_IMM(s2, 3, REG_ITMP2);
1697 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1698 M_LLD(d, REG_ITMP1, OFFSET(java_longarray, data[0]));
1699 store_reg_to_var_int(iptr->dst, d);
1702 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1704 var_to_reg_int(s1, src->prev, REG_ITMP1);
1705 var_to_reg_int(s2, src, REG_ITMP2);
1706 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1707 if (iptr->op1 == 0) {
1708 gen_nullptr_check(s1);
1711 M_ASLL_IMM(s2, 2, REG_ITMP2);
1712 M_AADD(REG_ITMP2, 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_FTMP3);
1722 if (iptr->op1 == 0) {
1723 gen_nullptr_check(s1);
1726 M_ASLL_IMM(s2, 3, REG_ITMP2);
1727 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1728 M_DLD(d, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1729 store_reg_to_var_flt(iptr->dst, d);
1732 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1734 var_to_reg_int(s1, src->prev, REG_ITMP1);
1735 var_to_reg_int(s2, src, REG_ITMP2);
1736 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1737 if (iptr->op1 == 0) {
1738 gen_nullptr_check(s1);
1741 M_AADD(s2, s1, REG_ITMP1);
1742 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1743 M_SLDU(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1744 store_reg_to_var_int(iptr->dst, d);
1747 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1749 var_to_reg_int(s1, src->prev, REG_ITMP1);
1750 var_to_reg_int(s2, src, REG_ITMP2);
1751 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1752 if (iptr->op1 == 0) {
1753 gen_nullptr_check(s1);
1756 M_AADD(s2, s1, REG_ITMP1);
1757 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1758 M_SLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1759 store_reg_to_var_int(iptr->dst, d);
1762 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1764 var_to_reg_int(s1, src->prev, REG_ITMP1);
1765 var_to_reg_int(s2, src, REG_ITMP2);
1766 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1767 if (iptr->op1 == 0) {
1768 gen_nullptr_check(s1);
1771 M_AADD(s2, s1, REG_ITMP1);
1772 M_BLDS(d, REG_ITMP1, OFFSET(java_chararray, data[0]));
1773 store_reg_to_var_int(iptr->dst, d);
1777 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1779 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1780 var_to_reg_int(s2, src->prev, REG_ITMP2);
1781 if (iptr->op1 == 0) {
1782 gen_nullptr_check(s1);
1785 var_to_reg_int(s3, src, REG_ITMP3);
1786 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1787 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1788 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1791 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1793 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1794 var_to_reg_int(s2, src->prev, REG_ITMP2);
1795 if (iptr->op1 == 0) {
1796 gen_nullptr_check(s1);
1799 var_to_reg_int(s3, src, REG_ITMP3);
1800 M_ASLL_IMM(s2, 2, REG_ITMP2);
1801 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1802 M_IST(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1805 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1807 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1808 var_to_reg_int(s2, src->prev, REG_ITMP2);
1809 if (iptr->op1 == 0) {
1810 gen_nullptr_check(s1);
1813 var_to_reg_int(s3, src, REG_ITMP3);
1814 M_ASLL_IMM(s2, 3, REG_ITMP2);
1815 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1816 M_LST(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1819 case ICMD_FASTORE: /* ..., 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_flt(s3, src, REG_FTMP3);
1828 M_ASLL_IMM(s2, 2, REG_ITMP2);
1829 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1830 M_FST(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1833 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1835 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1836 var_to_reg_int(s2, src->prev, REG_ITMP2);
1837 if (iptr->op1 == 0) {
1838 gen_nullptr_check(s1);
1841 var_to_reg_flt(s3, src, REG_FTMP3);
1842 M_ASLL_IMM(s2, 3, REG_ITMP2);
1843 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1844 M_DST(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1847 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1848 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1850 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1851 var_to_reg_int(s2, src->prev, REG_ITMP2);
1852 if (iptr->op1 == 0) {
1853 gen_nullptr_check(s1);
1856 var_to_reg_int(s3, src, REG_ITMP3);
1857 M_AADD(s2, s1, REG_ITMP1);
1858 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1859 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1862 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1864 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1865 var_to_reg_int(s2, src->prev, REG_ITMP2);
1866 if (iptr->op1 == 0) {
1867 gen_nullptr_check(s1);
1870 var_to_reg_int(s3, src, REG_ITMP3);
1871 M_AADD(s2, s1, REG_ITMP1);
1872 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1876 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1878 var_to_reg_int(s1, src->prev, REG_ITMP1);
1879 var_to_reg_int(s2, src, REG_ITMP2);
1880 if (iptr->op1 == 0) {
1881 gen_nullptr_check(s1);
1884 M_ASLL_IMM(s2, 2, REG_ITMP2);
1885 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1886 M_IST(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1889 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1891 var_to_reg_int(s1, src->prev, REG_ITMP1);
1892 var_to_reg_int(s2, src, REG_ITMP2);
1893 if (iptr->op1 == 0) {
1894 gen_nullptr_check(s1);
1897 M_ASLL_IMM(s2, 3, REG_ITMP2);
1898 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1899 M_LST(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1902 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1904 var_to_reg_int(s1, src->prev, REG_ITMP1);
1905 var_to_reg_int(s2, src, REG_ITMP2);
1906 if (iptr->op1 == 0) {
1907 gen_nullptr_check(s1);
1910 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1911 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1912 M_AST(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1915 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1917 var_to_reg_int(s1, src->prev, REG_ITMP1);
1918 var_to_reg_int(s2, src, REG_ITMP2);
1919 if (iptr->op1 == 0) {
1920 gen_nullptr_check(s1);
1923 M_AADD(s2, s1, REG_ITMP1);
1924 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1927 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1928 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1930 var_to_reg_int(s1, src->prev, REG_ITMP1);
1931 var_to_reg_int(s2, src, REG_ITMP2);
1932 if (iptr->op1 == 0) {
1933 gen_nullptr_check(s1);
1936 M_AADD(s2, s1, REG_ITMP1);
1937 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1938 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
1942 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1943 /* op1 = type, val.a = field address */
1945 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1946 codegen_addpatchref(cd, mcodeptr, asm_check_clinit,
1947 ((fieldinfo *) iptr->val.a)->class);
1949 /* This is just for debugging purposes. Is very difficult to */
1950 /* read patched code. Here we patch the following 2 nop's */
1951 /* so that the real code keeps untouched. */
1952 if (showdisassemble) {
1957 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1958 M_ALD(REG_ITMP1, REG_PV, a);
1959 switch (iptr->op1) {
1961 var_to_reg_int(s2, src, REG_ITMP2);
1962 M_IST(s2, REG_ITMP1, 0);
1965 var_to_reg_int(s2, src, REG_ITMP2);
1966 M_LST(s2, REG_ITMP1, 0);
1969 var_to_reg_int(s2, src, REG_ITMP2);
1970 M_AST(s2, REG_ITMP1, 0);
1973 var_to_reg_flt(s2, src, REG_FTMP2);
1974 M_FST(s2, REG_ITMP1, 0);
1977 var_to_reg_flt(s2, src, REG_FTMP2);
1978 M_DST(s2, REG_ITMP1, 0);
1983 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1984 /* val = value (in current instruction) */
1985 /* op1 = type, val.a = field address (in */
1986 /* following NOP) */
1988 if (!((fieldinfo *) iptr[1].val.a)->class->initialized) {
1989 codegen_addpatchref(cd, mcodeptr, asm_check_clinit,
1990 ((fieldinfo *) iptr[1].val.a)->class);
1992 if (showdisassemble) {
1997 a = dseg_addaddress(cd, &(((fieldinfo *) iptr[1].val.a)->value));
1998 M_ALD(REG_ITMP1, REG_PV, a);
1999 switch (iptr->op1) {
2001 M_IST(REG_ZERO, REG_ITMP1, 0);
2004 M_LST(REG_ZERO, REG_ITMP1, 0);
2007 M_AST(REG_ZERO, REG_ITMP1, 0);
2010 M_FST(REG_ZERO, REG_ITMP1, 0);
2013 M_DST(REG_ZERO, REG_ITMP1, 0);
2018 case ICMD_GETSTATIC: /* ... ==> ..., value */
2019 /* op1 = type, val.a = field address */
2021 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
2022 codegen_addpatchref(cd, mcodeptr, asm_check_clinit,
2023 ((fieldinfo *) iptr->val.a)->class);
2025 if (showdisassemble) {
2030 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
2031 M_ALD(REG_ITMP1, REG_PV, a);
2032 switch (iptr->op1) {
2034 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2035 M_ILD(d, REG_ITMP1, 0);
2036 store_reg_to_var_int(iptr->dst, d);
2039 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2040 M_LLD(d, REG_ITMP1, 0);
2041 store_reg_to_var_int(iptr->dst, d);
2044 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2045 M_ALD(d, REG_ITMP1, 0);
2046 store_reg_to_var_int(iptr->dst, d);
2049 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2050 M_FLD(d, REG_ITMP1, 0);
2051 store_reg_to_var_flt(iptr->dst, d);
2054 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2055 M_DLD(d, REG_ITMP1, 0);
2056 store_reg_to_var_flt(iptr->dst, d);
2062 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2063 /* op1 = type, val.a = field address */
2065 a = ((fieldinfo *) iptr->val.a)->offset;
2066 var_to_reg_int(s1, src->prev, REG_ITMP1);
2067 gen_nullptr_check(s1);
2068 switch (iptr->op1) {
2070 var_to_reg_int(s2, src, REG_ITMP2);
2074 var_to_reg_int(s2, src, REG_ITMP2);
2078 var_to_reg_int(s2, src, REG_ITMP2);
2082 var_to_reg_flt(s2, src, REG_FTMP2);
2086 var_to_reg_flt(s2, src, REG_FTMP2);
2092 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
2093 /* val = value (in current instruction) */
2094 /* op1 = type, val.a = field address (in */
2095 /* following NOP) */
2097 a = ((fieldinfo *) iptr[1].val.a)->offset;
2098 var_to_reg_int(s1, src, REG_ITMP1);
2099 gen_nullptr_check(s1);
2100 switch (iptr->op1) {
2102 M_IST(REG_ZERO, s1, a);
2105 M_LST(REG_ZERO, s1, a);
2108 M_AST(REG_ZERO, s1, a);
2111 M_FST(REG_ZERO, s1, a);
2114 M_DST(REG_ZERO, s1, a);
2119 case ICMD_GETFIELD: /* ... ==> ..., value */
2120 /* op1 = type, val.i = field offset */
2122 a = ((fieldinfo *)(iptr->val.a))->offset;
2123 var_to_reg_int(s1, src, REG_ITMP1);
2124 gen_nullptr_check(s1);
2125 switch (iptr->op1) {
2127 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2129 store_reg_to_var_int(iptr->dst, d);
2132 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2134 store_reg_to_var_int(iptr->dst, d);
2137 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2139 store_reg_to_var_int(iptr->dst, d);
2142 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2144 store_reg_to_var_flt(iptr->dst, d);
2147 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2149 store_reg_to_var_flt(iptr->dst, d);
2155 /* branch operations **************************************************/
2157 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2159 var_to_reg_int(s1, src, REG_ITMP1);
2160 M_INTMOVE(s1, REG_ITMP1_XPTR);
2161 a = dseg_addaddress(cd, asm_handle_exception);
2162 M_ALD(REG_ITMP2, REG_PV, a);
2163 M_JSR(REG_ITMP2_XPC, REG_ITMP2);
2165 M_NOP; /* nop ensures that XPC is less than the end */
2166 /* of basic block */
2170 case ICMD_GOTO: /* ... ==> ... */
2171 /* op1 = target JavaVM pc */
2173 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2178 case ICMD_JSR: /* ... ==> ... */
2179 /* op1 = target JavaVM pc */
2181 dseg_addtarget(cd, BlockPtrOfPC(iptr->op1));
2182 M_ALD(REG_ITMP1, REG_PV, -(cd->dseglen));
2183 M_JSR(REG_ITMP1, REG_ITMP1); /* REG_ITMP1 = return address */
2187 case ICMD_RET: /* ... ==> ... */
2188 /* op1 = local variable */
2189 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2190 if (var->flags & INMEMORY) {
2191 M_ALD(REG_ITMP1, REG_SP, 8 * var->regoff);
2200 case ICMD_IFNULL: /* ..., value ==> ... */
2201 /* op1 = target JavaVM pc */
2203 var_to_reg_int(s1, src, REG_ITMP1);
2205 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2209 case ICMD_IFNONNULL: /* ..., value ==> ... */
2210 /* op1 = target JavaVM pc */
2212 var_to_reg_int(s1, src, REG_ITMP1);
2214 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2218 case ICMD_IFEQ: /* ..., value ==> ... */
2219 /* op1 = target JavaVM pc, val.i = constant */
2221 var_to_reg_int(s1, src, REG_ITMP1);
2222 if (iptr->val.i == 0) {
2226 ICONST(REG_ITMP2, iptr->val.i);
2227 M_BEQ(s1, REG_ITMP2, 0);
2229 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2233 case ICMD_IFLT: /* ..., value ==> ... */
2234 /* op1 = target JavaVM pc, val.i = constant */
2236 var_to_reg_int(s1, src, REG_ITMP1);
2237 if (iptr->val.i == 0) {
2241 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2242 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2245 ICONST(REG_ITMP2, iptr->val.i);
2246 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2248 M_BNEZ(REG_ITMP1, 0);
2250 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2254 case ICMD_IFLE: /* ..., value ==> ... */
2255 /* op1 = target JavaVM pc, val.i = constant */
2257 var_to_reg_int(s1, src, REG_ITMP1);
2258 if (iptr->val.i == 0) {
2262 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2263 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2264 M_BNEZ(REG_ITMP1, 0);
2267 ICONST(REG_ITMP2, iptr->val.i);
2268 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2269 M_BEQZ(REG_ITMP1, 0);
2272 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2276 case ICMD_IFNE: /* ..., value ==> ... */
2277 /* op1 = target JavaVM pc, val.i = constant */
2279 var_to_reg_int(s1, src, REG_ITMP1);
2280 if (iptr->val.i == 0) {
2284 ICONST(REG_ITMP2, iptr->val.i);
2285 M_BNE(s1, REG_ITMP2, 0);
2287 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2291 case ICMD_IFGT: /* ..., value ==> ... */
2292 /* op1 = target JavaVM pc, val.i = constant */
2294 var_to_reg_int(s1, src, REG_ITMP1);
2295 if (iptr->val.i == 0) {
2299 if ((iptr->val.i >= -32769) && (iptr->val.i <= 32766)) {
2300 M_CMPLT_IMM(s1, iptr->val.i + 1, REG_ITMP1);
2301 M_BEQZ(REG_ITMP1, 0);
2304 ICONST(REG_ITMP2, iptr->val.i);
2305 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2306 M_BNEZ(REG_ITMP1, 0);
2309 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2313 case ICMD_IFGE: /* ..., value ==> ... */
2314 /* op1 = target JavaVM pc, val.i = constant */
2316 var_to_reg_int(s1, src, REG_ITMP1);
2317 if (iptr->val.i == 0) {
2321 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2322 M_CMPLT_IMM(s1, iptr->val.i, REG_ITMP1);
2325 ICONST(REG_ITMP2, iptr->val.i);
2326 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2328 M_BEQZ(REG_ITMP1, 0);
2330 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2334 case ICMD_IF_LEQ: /* ..., value ==> ... */
2335 /* op1 = target JavaVM pc, val.l = constant */
2337 var_to_reg_int(s1, src, REG_ITMP1);
2338 if (iptr->val.l == 0) {
2342 LCONST(REG_ITMP2, iptr->val.l);
2343 M_BEQ(s1, REG_ITMP2, 0);
2345 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2349 case ICMD_IF_LLT: /* ..., value ==> ... */
2350 /* op1 = target JavaVM pc, val.l = constant */
2352 var_to_reg_int(s1, src, REG_ITMP1);
2353 if (iptr->val.l == 0) {
2357 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2358 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2361 LCONST(REG_ITMP2, iptr->val.l);
2362 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2364 M_BNEZ(REG_ITMP1, 0);
2366 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2370 case ICMD_IF_LLE: /* ..., value ==> ... */
2371 /* op1 = target JavaVM pc, val.l = constant */
2373 var_to_reg_int(s1, src, REG_ITMP1);
2374 if (iptr->val.l == 0) {
2378 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2379 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2380 M_BNEZ(REG_ITMP1, 0);
2383 LCONST(REG_ITMP2, iptr->val.l);
2384 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2385 M_BEQZ(REG_ITMP1, 0);
2388 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2392 case ICMD_IF_LNE: /* ..., value ==> ... */
2393 /* op1 = target JavaVM pc, val.l = constant */
2395 var_to_reg_int(s1, src, REG_ITMP1);
2396 if (iptr->val.l == 0) {
2400 LCONST(REG_ITMP2, iptr->val.l);
2401 M_BNE(s1, REG_ITMP2, 0);
2403 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2407 case ICMD_IF_LGT: /* ..., value ==> ... */
2408 /* op1 = target JavaVM pc, val.l = constant */
2410 var_to_reg_int(s1, src, REG_ITMP1);
2411 if (iptr->val.l == 0) {
2415 if ((iptr->val.l >= -32769) && (iptr->val.l <= 32766)) {
2416 M_CMPLT_IMM(s1, iptr->val.l + 1, REG_ITMP1);
2417 M_BEQZ(REG_ITMP1, 0);
2420 LCONST(REG_ITMP2, iptr->val.l);
2421 M_CMPGT(s1, REG_ITMP2, REG_ITMP1);
2422 M_BNEZ(REG_ITMP1, 0);
2425 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2429 case ICMD_IF_LGE: /* ..., value ==> ... */
2430 /* op1 = target JavaVM pc, val.l = constant */
2432 var_to_reg_int(s1, src, REG_ITMP1);
2433 if (iptr->val.l == 0) {
2437 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2438 M_CMPLT_IMM(s1, iptr->val.l, REG_ITMP1);
2441 LCONST(REG_ITMP2, iptr->val.l);
2442 M_CMPLT(s1, REG_ITMP2, REG_ITMP1);
2444 M_BEQZ(REG_ITMP1, 0);
2446 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2450 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2451 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2452 case ICMD_IF_ACMPEQ:
2454 var_to_reg_int(s1, src->prev, REG_ITMP1);
2455 var_to_reg_int(s2, src, REG_ITMP2);
2457 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2461 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2462 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2463 case ICMD_IF_ACMPNE:
2465 var_to_reg_int(s1, src->prev, REG_ITMP1);
2466 var_to_reg_int(s2, src, REG_ITMP2);
2468 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2472 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2473 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2475 var_to_reg_int(s1, src->prev, REG_ITMP1);
2476 var_to_reg_int(s2, src, REG_ITMP2);
2477 M_CMPLT(s1, s2, REG_ITMP1);
2478 M_BNEZ(REG_ITMP1, 0);
2479 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2483 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2484 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2486 var_to_reg_int(s1, src->prev, REG_ITMP1);
2487 var_to_reg_int(s2, src, REG_ITMP2);
2488 M_CMPGT(s1, s2, REG_ITMP1);
2489 M_BNEZ(REG_ITMP1, 0);
2490 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2494 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2495 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2497 var_to_reg_int(s1, src->prev, REG_ITMP1);
2498 var_to_reg_int(s2, src, REG_ITMP2);
2499 M_CMPGT(s1, s2, REG_ITMP1);
2500 M_BEQZ(REG_ITMP1, 0);
2501 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2505 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2506 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2508 var_to_reg_int(s1, src->prev, REG_ITMP1);
2509 var_to_reg_int(s2, src, REG_ITMP2);
2510 M_CMPLT(s1, s2, REG_ITMP1);
2511 M_BEQZ(REG_ITMP1, 0);
2512 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2516 #ifdef CONDITIONAL_LOADCONST
2517 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2519 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2522 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2523 /* val.i = constant */
2525 var_to_reg_int(s1, src, REG_ITMP1);
2526 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2528 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2529 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2530 M_CMPEQ(s1, REG_ZERO, d);
2531 store_reg_to_var_int(iptr->dst, d);
2534 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2535 M_CMPEQ(s1, REG_ZERO, d);
2537 store_reg_to_var_int(iptr->dst, d);
2541 M_MOV(s1, REG_ITMP1);
2544 ICONST(d, iptr[1].val.i);
2546 if ((s3 >= 0) && (s3 <= 255)) {
2547 M_CMOVEQ_IMM(s1, s3, d);
2550 ICONST(REG_ITMP2, s3);
2551 M_CMOVEQ(s1, REG_ITMP2, d);
2553 store_reg_to_var_int(iptr->dst, d);
2556 case ICMD_IFNE_ICONST: /* ..., value ==> ..., constant */
2557 /* val.i = constant */
2559 var_to_reg_int(s1, src, REG_ITMP1);
2560 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2562 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2563 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2564 M_CMPEQ(s1, REG_ZERO, d);
2565 store_reg_to_var_int(iptr->dst, d);
2568 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2569 M_CMPEQ(s1, REG_ZERO, d);
2571 store_reg_to_var_int(iptr->dst, d);
2575 M_MOV(s1, REG_ITMP1);
2578 ICONST(d, iptr[1].val.i);
2580 if ((s3 >= 0) && (s3 <= 255)) {
2581 M_CMOVNE_IMM(s1, s3, d);
2584 ICONST(REG_ITMP2, s3);
2585 M_CMOVNE(s1, REG_ITMP2, d);
2587 store_reg_to_var_int(iptr->dst, d);
2590 case ICMD_IFLT_ICONST: /* ..., value ==> ..., constant */
2591 /* val.i = constant */
2593 var_to_reg_int(s1, src, REG_ITMP1);
2594 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2596 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2597 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2598 M_CMPLT(s1, REG_ZERO, d);
2599 store_reg_to_var_int(iptr->dst, d);
2602 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2603 M_CMPLE(REG_ZERO, s1, d);
2604 store_reg_to_var_int(iptr->dst, d);
2608 M_MOV(s1, REG_ITMP1);
2611 ICONST(d, iptr[1].val.i);
2613 if ((s3 >= 0) && (s3 <= 255)) {
2614 M_CMOVLT_IMM(s1, s3, d);
2617 ICONST(REG_ITMP2, s3);
2618 M_CMOVLT(s1, REG_ITMP2, d);
2620 store_reg_to_var_int(iptr->dst, d);
2623 case ICMD_IFGE_ICONST: /* ..., value ==> ..., constant */
2624 /* val.i = constant */
2626 var_to_reg_int(s1, src, REG_ITMP1);
2627 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2629 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2630 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2631 M_CMPLE(REG_ZERO, s1, d);
2632 store_reg_to_var_int(iptr->dst, d);
2635 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2636 M_CMPLT(s1, REG_ZERO, d);
2637 store_reg_to_var_int(iptr->dst, d);
2641 M_MOV(s1, REG_ITMP1);
2644 ICONST(d, iptr[1].val.i);
2646 if ((s3 >= 0) && (s3 <= 255)) {
2647 M_CMOVGE_IMM(s1, s3, d);
2650 ICONST(REG_ITMP2, s3);
2651 M_CMOVGE(s1, REG_ITMP2, d);
2653 store_reg_to_var_int(iptr->dst, d);
2656 case ICMD_IFGT_ICONST: /* ..., value ==> ..., constant */
2657 /* val.i = constant */
2659 var_to_reg_int(s1, src, REG_ITMP1);
2660 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2662 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2663 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2664 M_CMPLT(REG_ZERO, s1, d);
2665 store_reg_to_var_int(iptr->dst, d);
2668 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2669 M_CMPLE(s1, REG_ZERO, d);
2670 store_reg_to_var_int(iptr->dst, d);
2674 M_MOV(s1, REG_ITMP1);
2677 ICONST(d, iptr[1].val.i);
2679 if ((s3 >= 0) && (s3 <= 255)) {
2680 M_CMOVGT_IMM(s1, s3, d);
2683 ICONST(REG_ITMP2, s3);
2684 M_CMOVGT(s1, REG_ITMP2, d);
2686 store_reg_to_var_int(iptr->dst, d);
2689 case ICMD_IFLE_ICONST: /* ..., value ==> ..., constant */
2690 /* val.i = constant */
2692 var_to_reg_int(s1, src, REG_ITMP1);
2693 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2695 if ((iptr[1].opc == ICMD_ELSE_ICONST)) {
2696 if ((s3 == 1) && (iptr[1].val.i == 0)) {
2697 M_CMPLE(s1, REG_ZERO, d);
2698 store_reg_to_var_int(iptr->dst, d);
2701 if ((s3 == 0) && (iptr[1].val.i == 1)) {
2702 M_CMPLT(REG_ZERO, s1, d);
2703 store_reg_to_var_int(iptr->dst, d);
2707 M_MOV(s1, REG_ITMP1);
2710 ICONST(d, iptr[1].val.i);
2712 if ((s3 >= 0) && (s3 <= 255)) {
2713 M_CMOVLE_IMM(s1, s3, d);
2716 ICONST(REG_ITMP2, s3);
2717 M_CMOVLE(s1, REG_ITMP2, d);
2719 store_reg_to_var_int(iptr->dst, d);
2724 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2727 var_to_reg_int(s1, src, REG_RESULT);
2728 M_INTMOVE(s1, REG_RESULT);
2730 #if defined(USE_THREADS)
2731 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2733 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2734 M_ALD(REG_ITMP3, REG_PV, a);
2735 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
2736 M_JSR(REG_RA, REG_ITMP3);
2737 M_LST(REG_RESULT, REG_SP, rd->maxmemuse * 8); /* delay slot */
2739 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2740 M_LDA(REG_PV, REG_RA, disp);
2741 M_LLD(REG_RESULT, REG_SP, rd->maxmemuse * 8);
2744 goto nowperformreturn;
2746 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2748 var_to_reg_flt(s1, src, REG_FRESULT);
2750 int t = ((iptr->opc == ICMD_FRETURN) ? TYPE_FLT : TYPE_DBL);
2751 M_TFLTMOVE(t, s1, REG_FRESULT);
2754 #if defined(USE_THREADS)
2755 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2757 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2758 M_ALD(REG_ITMP3, REG_PV, a);
2759 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8);
2760 M_JSR(REG_RA, REG_ITMP3);
2761 M_DST(REG_FRESULT, REG_SP, rd->maxmemuse * 8); /* delay slot */
2763 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2764 M_LDA(REG_PV, REG_RA, disp);
2765 M_DLD(REG_FRESULT, REG_SP, rd->maxmemuse * 8);
2768 goto nowperformreturn;
2770 case ICMD_RETURN: /* ... ==> ... */
2772 #if defined(USE_THREADS)
2773 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2775 a = dseg_addaddress(cd, (void *) builtin_monitorexit);
2776 M_ALD(REG_ITMP3, REG_PV, a);
2777 M_JSR(REG_RA, REG_ITMP3);
2778 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 8); /* delay slot */
2779 disp = -(s4) ((u1 *) mcodeptr - cd->mcodebase);
2780 M_LDA(REG_PV, REG_RA, disp);
2788 p = parentargs_base;
2790 /* restore return address */
2792 if (!m->isleafmethod) {
2793 p--; M_LLD(REG_RA, REG_SP, 8 * p);
2796 /* restore saved registers */
2798 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2799 p--; M_LLD(rd->savintregs[i], REG_SP, 8 * p);
2801 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2802 p--; M_DLD(rd->savfltregs[i], REG_SP, 8 * p);
2805 /* call trace function */
2808 M_LDA (REG_SP, REG_SP, -24);
2809 M_LST(REG_RA, REG_SP, 0);
2810 M_LST(REG_RESULT, REG_SP, 8);
2811 M_DST(REG_FRESULT, REG_SP,16);
2812 a = dseg_addaddress(cd, m);
2813 M_ALD(rd->argintregs[0], REG_PV, a);
2814 M_MOV(REG_RESULT, rd->argintregs[1]);
2815 M_FLTMOVE(REG_FRESULT, rd->argfltregs[2]);
2816 M_FMOV(REG_FRESULT, rd->argfltregs[3]);
2817 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2818 M_ALD(REG_ITMP3, REG_PV, a);
2819 M_JSR (REG_RA, REG_ITMP3);
2821 M_DLD(REG_FRESULT, REG_SP,16);
2822 M_LLD(REG_RESULT, REG_SP, 8);
2823 M_LLD(REG_RA, REG_SP, 0);
2824 M_LDA (REG_SP, REG_SP, 24);
2829 /* deallocate stack */
2831 if (parentargs_base) {
2832 M_LDA(REG_SP, REG_SP, parentargs_base * 8);
2843 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2848 tptr = (void **) iptr->target;
2850 s4ptr = iptr->val.a;
2851 l = s4ptr[1]; /* low */
2852 i = s4ptr[2]; /* high */
2854 var_to_reg_int(s1, src, REG_ITMP1);
2856 {M_INTMOVE(s1, REG_ITMP1);}
2857 else if (l <= 32768) {
2858 M_IADD_IMM(s1, -l, REG_ITMP1);
2861 ICONST(REG_ITMP2, l);
2862 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2868 M_CMPULT_IMM(REG_ITMP1, i, REG_ITMP2);
2869 M_BEQZ(REG_ITMP2, 0);
2870 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2871 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1); /* delay slot*/
2873 /* build jump table top down and use address of lowest entry */
2875 /* s4ptr += 3 + i; */
2879 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2880 dseg_addtarget(cd, (basicblock *) tptr[0]);
2885 /* length of dataseg after last dseg_addtarget is used by load */
2887 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2888 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2895 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2897 s4 i, /*l, */val, *s4ptr;
2900 tptr = (void **) iptr->target;
2902 s4ptr = iptr->val.a;
2903 /*l = s4ptr[0];*/ /* default */
2904 i = s4ptr[1]; /* count */
2906 MCODECHECK((i<<2)+8);
2907 var_to_reg_int(s1, src, REG_ITMP1);
2913 ICONST(REG_ITMP2, val);
2914 M_BEQ(s1, REG_ITMP2, 0);
2915 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2920 tptr = (void **) iptr->target;
2921 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2928 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2929 /* op1 = return type, val.a = function pointer*/
2933 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2934 /* op1 = return type, val.a = function pointer*/
2938 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2939 /* op1 = return type, val.a = function pointer*/
2943 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2944 /* op1 = arg count, val.a = method pointer */
2946 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2947 /* op1 = arg count, val.a = method pointer */
2949 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2950 /* op1 = arg count, val.a = method pointer */
2952 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2953 /* op1 = arg count, val.a = method pointer */
2960 MCODECHECK((s3 << 1) + 64);
2962 /* copy arguments to registers or stack location */
2964 for (; --s3 >= 0; src = src->prev) {
2965 if (src->varkind == ARGVAR)
2967 if (IS_INT_LNG_TYPE(src->type)) {
2968 if (s3 < INT_ARG_CNT) {
2969 s1 = rd->argintregs[s3];
2970 var_to_reg_int(d, src, s1);
2974 var_to_reg_int(d, src, REG_ITMP1);
2975 M_LST(d, REG_SP, 8 * (s3 - INT_ARG_CNT));
2979 if (s3 < FLT_ARG_CNT) {
2980 s1 = rd->argfltregs[s3];
2981 var_to_reg_flt(d, src, s1);
2982 M_TFLTMOVE(src->type, d, s1);
2985 var_to_reg_flt(d, src, REG_FTMP1);
2986 M_DST(d, REG_SP, 8 * (s3 - FLT_ARG_CNT));
2992 switch (iptr->opc) {
2996 a = dseg_addaddress(cd, (void *) lm);
2997 d = iptr->op1; /* return type */
2999 M_ALD(REG_ITMP3, REG_PV, a); /* built-in-function pointer */
3000 M_JSR(REG_RA, REG_ITMP3);
3002 goto afteractualcall;
3004 case ICMD_INVOKESTATIC:
3005 case ICMD_INVOKESPECIAL:
3006 a = dseg_addaddress(cd, lm->stubroutine);
3009 M_ALD(REG_PV, REG_PV, a); /* method pointer in pv */
3012 case ICMD_INVOKEVIRTUAL:
3015 gen_nullptr_check(rd->argintregs[0]);
3016 M_ALD(REG_METHODPTR, rd->argintregs[0], OFFSET(java_objectheader, vftbl));
3017 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * lm->vftblindex);
3020 case ICMD_INVOKEINTERFACE:
3023 gen_nullptr_check(rd->argintregs[0]);
3024 M_ALD(REG_METHODPTR, rd->argintregs[0], OFFSET(java_objectheader, vftbl));
3025 M_ALD(REG_METHODPTR, REG_METHODPTR, OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->class->index);
3026 M_ALD(REG_PV, REG_METHODPTR, sizeof(methodptr) * (lm - lm->class->methods));
3030 M_JSR(REG_RA, REG_PV);
3037 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3038 if (s1 <= 32768) M_LDA(REG_PV, REG_RA, -s1);
3040 s4 ml = -s1, mh = 0;
3041 while (ml < -32768) { ml += 65536; mh--; }
3043 M_IADD_IMM(REG_PV, ml, REG_PV);
3044 M_LADD(REG_PV, REG_RA, REG_PV);
3047 /* d contains return type */
3049 if (d != TYPE_VOID) {
3050 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3051 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3052 M_INTMOVE(REG_RESULT, s1);
3053 store_reg_to_var_int(iptr->dst, s1);
3056 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3057 M_TFLTMOVE(iptr->dst->type, REG_FRESULT, s1);
3058 store_reg_to_var_flt(iptr->dst, s1);
3065 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3067 /* op1: 0 == array, 1 == class */
3068 /* val.a: (classinfo*) superclass */
3070 /* superclass is an interface:
3072 * return (sub != NULL) &&
3073 * (sub->vftbl->interfacetablelength > super->index) &&
3074 * (sub->vftbl->interfacetable[-super->index] != NULL);
3076 * superclass is a class:
3078 * return ((sub != NULL) && (0
3079 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3080 * super->vftbl->diffvall));
3084 classinfo *super = (classinfo*) iptr->val.a;
3086 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3087 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3089 var_to_reg_int(s1, src, REG_ITMP1);
3090 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3092 M_MOV(s1, REG_ITMP1);
3096 if (iptr->op1) { /* class/interface */
3097 if (super->flags & ACC_INTERFACE) { /* interface */
3100 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3101 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3102 M_IADD_IMM(REG_ITMP2, - super->index, REG_ITMP2);
3103 M_BLEZ(REG_ITMP2, 3);
3105 M_ALD(REG_ITMP1, REG_ITMP1,
3106 OFFSET(vftbl_t, interfacetable[0]) -
3107 super->index * sizeof(methodptr*));
3108 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3112 s2 = super->vftbl->diffval;
3115 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3116 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3117 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3118 M_CMPULT_IMM(REG_ITMP1, s2 + 1, d);
3123 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3124 a = dseg_addaddress(cd, (void *) super->vftbl);
3125 M_ALD(REG_ITMP2, REG_PV, a);
3126 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3127 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3129 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3130 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3131 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3132 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3133 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3135 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3136 M_CMPULT(REG_ITMP2, REG_ITMP1, d);
3142 panic ("internal error: no inlined array instanceof");
3144 store_reg_to_var_int(iptr->dst, d);
3147 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3149 /* op1: 0 == array, 1 == class */
3150 /* val.a: (classinfo*) superclass */
3152 /* superclass is an interface:
3154 * OK if ((sub == NULL) ||
3155 * (sub->vftbl->interfacetablelength > super->index) &&
3156 * (sub->vftbl->interfacetable[-super->index] != NULL));
3158 * superclass is a class:
3160 * OK if ((sub == NULL) || (0
3161 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3162 * super->vftbl->diffvall));
3166 classinfo *super = (classinfo *) iptr->val.a;
3168 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3169 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
3172 var_to_reg_int(s1, src, REG_ITMP1);
3173 if (iptr->op1) { /* class/interface */
3174 if (super->flags & ACC_INTERFACE) { /* interface */
3177 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3178 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3179 M_IADD_IMM(REG_ITMP3, - super->index, REG_ITMP3);
3180 M_BLEZ(REG_ITMP3, 0);
3181 codegen_addxcastrefs(cd, mcodeptr);
3183 M_ALD(REG_ITMP3, REG_ITMP2,
3184 OFFSET(vftbl_t, interfacetable[0]) -
3185 super->index * sizeof(methodptr*));
3186 M_BEQZ(REG_ITMP3, 0);
3187 codegen_addxcastrefs(cd, mcodeptr);
3190 } else { /* class */
3193 s2 = super->vftbl->diffval;
3194 M_BEQZ(s1, 6 + (s2 != 0));
3196 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3197 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3198 M_IADD_IMM(REG_ITMP1, - super->vftbl->baseval, REG_ITMP1);
3200 M_BNEZ(REG_ITMP1, 0);
3203 M_CMPULT_IMM(REG_ITMP1, s2 + 1, REG_ITMP2);
3204 M_BEQZ(REG_ITMP2, 0);
3208 M_BEQZ(s1, 10 + (s1 == REG_ITMP1));
3210 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3211 a = dseg_addaddress(cd, (void *) super->vftbl);
3212 M_ALD(REG_ITMP3, REG_PV, a);
3213 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3214 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3216 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3217 if (s1 != REG_ITMP1) {
3218 M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval));
3219 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3220 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3221 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3223 M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2);
3225 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3226 M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
3227 M_ALD(REG_ITMP3, REG_PV, a);
3228 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3229 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3230 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3233 M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3234 M_BNEZ(REG_ITMP3, 0);
3236 codegen_addxcastrefs(cd, mcodeptr);
3241 panic ("internal error: no inlined array checkcast");
3243 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3245 store_reg_to_var_int(iptr->dst, d);
3248 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3250 var_to_reg_int(s1, src, REG_ITMP1);
3252 codegen_addxcheckarefs(cd, mcodeptr);
3256 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3258 M_BEQZ(REG_RESULT, 0);
3259 codegen_addxexceptionrefs(cd, mcodeptr);
3263 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3264 /* op1 = dimension, val.a = array descriptor */
3266 /* check for negative sizes and copy sizes to stack if necessary */
3268 MCODECHECK((iptr->op1 << 1) + 64);
3270 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3271 var_to_reg_int(s2, src, REG_ITMP1);
3273 codegen_addxcheckarefs(cd, mcodeptr);
3276 /* copy SAVEDVAR sizes to stack */
3278 if (src->varkind != ARGVAR) {
3279 M_LST(s2, REG_SP, s1 * 8);
3283 /* a0 = dimension count */
3285 ICONST(rd->argintregs[0], iptr->op1);
3287 /* a1 = arraydescriptor */
3289 a = dseg_addaddress(cd, iptr->val.a);
3290 M_ALD(rd->argintregs[1], REG_PV, a);
3292 /* a2 = pointer to dimensions = stack pointer */
3294 M_INTMOVE(REG_SP, rd->argintregs[2]);
3296 a = dseg_addaddress(cd, (void*) builtin_nmultianewarray);
3297 M_ALD(REG_ITMP3, REG_PV, a);
3298 M_JSR(REG_RA, REG_ITMP3);
3300 s1 = (int)((u1*) mcodeptr - cd->mcodebase);
3302 M_LDA (REG_PV, REG_RA, -s1);
3306 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3307 M_INTMOVE(REG_RESULT, s1);
3308 store_reg_to_var_int(iptr->dst, s1);
3312 throw_cacao_exception_exit(string_java_lang_InternalError,
3313 "Unknown ICMD %d", iptr->opc);
3316 } /* for instruction */
3318 /* copy values to interface registers */
3320 src = bptr->outstack;
3321 len = bptr->outdepth;
3328 if ((src->varkind != STACKVAR)) {
3330 if (IS_FLT_DBL_TYPE(s2)) {
3331 var_to_reg_flt(s1, src, REG_FTMP1);
3332 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3333 M_TFLTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3336 M_DST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3340 var_to_reg_int(s1, src, REG_ITMP1);
3341 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3342 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3345 M_LST(s1, REG_SP, 8 * rd->interfaces[len][s2].regoff);
3351 } /* if (bptr -> flags >= BBREACHED) */
3352 } /* for basic block */
3355 /* generate bound check stubs */
3357 s4 *xcodeptr = NULL;
3360 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3361 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3363 (u1 *) mcodeptr - cd->mcodebase);
3367 M_MOV(bref->reg, REG_ITMP1);
3368 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3370 if (xcodeptr != NULL) {
3371 M_BR(xcodeptr - mcodeptr);
3375 xcodeptr = mcodeptr;
3377 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3378 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3380 M_MOV(REG_ITMP1, rd->argintregs[0]);
3381 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3382 M_ALD(REG_ITMP3, REG_PV, a);
3383 M_JSR(REG_RA, REG_ITMP3);
3385 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3387 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3388 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3390 a = dseg_addaddress(cd, asm_handle_exception);
3391 M_ALD(REG_ITMP3, REG_PV, a);
3397 /* generate negative array size check stubs */
3401 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3402 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3403 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3405 (u1 *) xcodeptr - cd->mcodebase - 4);
3409 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3411 (u1 *) mcodeptr - cd->mcodebase);
3415 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3417 if (xcodeptr != NULL) {
3418 M_BR(xcodeptr - mcodeptr);
3422 xcodeptr = mcodeptr;
3424 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3425 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3427 a = dseg_addaddress(cd, new_negativearraysizeexception);
3428 M_ALD(REG_ITMP3, REG_PV, a);
3429 M_JSR(REG_RA, REG_ITMP3);
3431 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3433 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3434 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3436 a = dseg_addaddress(cd, asm_handle_exception);
3437 M_ALD(REG_ITMP3, REG_PV, a);
3443 /* generate cast check stubs */
3447 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3448 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3449 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3451 (u1 *) xcodeptr - cd->mcodebase - 4);
3455 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3457 (u1 *) mcodeptr - cd->mcodebase);
3461 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3463 if (xcodeptr != NULL) {
3464 M_BR(xcodeptr - mcodeptr);
3468 xcodeptr = mcodeptr;
3470 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3471 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3473 a = dseg_addaddress(cd, new_classcastexception);
3474 M_ALD(REG_ITMP3, REG_PV, a);
3475 M_JSR(REG_RA, REG_ITMP3);
3477 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3479 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3480 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3482 a = dseg_addaddress(cd, asm_handle_exception);
3483 M_ALD(REG_ITMP3, REG_PV, a);
3489 /* generate exception check stubs */
3493 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3494 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3495 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3497 (u1 *) xcodeptr - cd->mcodebase - 4);
3501 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3503 (u1 *) mcodeptr - cd->mcodebase);
3507 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3509 if (xcodeptr != NULL) {
3510 M_BR(xcodeptr - mcodeptr);
3514 xcodeptr = mcodeptr;
3516 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3517 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3518 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3520 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3521 M_ALD(REG_ITMP3, REG_PV, a);
3522 M_JSR(REG_RA, REG_ITMP3);
3525 /* get the exceptionptr from the ptrprt and clear it */
3526 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3527 M_AST(REG_ZERO, REG_RESULT, 0);
3529 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3530 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3532 a = dseg_addaddress(cd, &_exceptionptr);
3533 M_ALD(REG_ITMP3, REG_PV, a);
3534 M_ALD(REG_ITMP1_XPTR, REG_ITMP3, 0);
3535 M_AST(REG_ZERO, REG_ITMP3, 0);
3538 a = dseg_addaddress(cd, asm_handle_exception);
3539 M_ALD(REG_ITMP3, REG_PV, a);
3545 /* generate null pointer check stubs */
3549 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3550 if ((cd->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3551 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3553 (u1 *) xcodeptr - cd->mcodebase - 4);
3557 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3559 (u1 *) mcodeptr - cd->mcodebase);
3563 M_LADD_IMM(REG_PV, bref->branchpos - 4, REG_ITMP2_XPC);
3565 if (xcodeptr != NULL) {
3566 M_BR(xcodeptr - mcodeptr);
3570 xcodeptr = mcodeptr;
3572 M_LSUB_IMM(REG_SP, 1 * 8, REG_SP);
3573 M_LST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3575 a = dseg_addaddress(cd, new_nullpointerexception);
3576 M_ALD(REG_ITMP3, REG_PV, a);
3577 M_JSR(REG_RA, REG_ITMP3);
3579 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3581 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3582 M_LADD_IMM(REG_SP, 1 * 8, REG_SP);
3584 a = dseg_addaddress(cd, asm_handle_exception);
3585 M_ALD(REG_ITMP3, REG_PV, a);
3592 /* generate put/getstatic stub call code */
3599 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3600 /* check code segment size */
3603 /* Get machine code which is patched back in later. The call is */
3604 /* 2 instruction words long. */
3605 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3607 /* We need to split this, because an unaligned 8 byte read causes */
3609 mcode = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
3611 /* patch in the call to call the following code (done at compile */
3614 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3615 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3617 M_BRS(tmpmcodeptr - (xcodeptr + 1));
3620 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3622 /* move class pointer into REG_ITMP1 */
3623 a = dseg_addaddress(cd, pref->ref);
3624 M_ALD(REG_ITMP1, REG_PV, a);
3626 /* move machine code into REG_ITMP2 */
3627 a = dseg_adds8(cd, mcode);
3628 M_LLD(REG_ITMP2, REG_PV, a);
3630 a = dseg_addaddress(cd, pref->asmwrapper);
3631 M_ALD(REG_ITMP3, REG_PV, a);
3638 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
3640 docacheflush((void*) m->entrypoint, ((u1*) mcodeptr - cd->mcodebase));
3644 /* function createcompilerstub *************************************************
3646 creates a stub routine which calls the compiler
3648 *******************************************************************************/
3650 #define COMPSTUB_SIZE 4
3652 u1 *createcompilerstub(methodinfo *m)
3654 u8 *s = CNEW(u8, COMPSTUB_SIZE); /* memory to hold the stub */
3655 s4 *mcodeptr = (s4 *) s; /* code generation pointer */
3657 /* code for the stub */
3658 M_ALD(REG_PV, REG_PV, 24); /* load pointer to the compiler */
3660 M_JSR(REG_ITMP1, REG_PV); /* jump to the compiler, return address
3661 in itmp1 is used as method pointer */
3664 s[2] = (u8) m; /* literals to be adressed */
3665 s[3] = (u8) asm_call_jit_compiler; /* jump directly via PV from above */
3667 (void) docacheflush((void*) s, (char*) mcodeptr - (char*) s);
3669 #if defined(STATISTICS)
3671 count_cstub_len += COMPSTUB_SIZE * 8;
3678 /* function removecompilerstub *************************************************
3680 deletes a compilerstub from memory (simply by freeing it)
3682 *******************************************************************************/
3684 void removecompilerstub(u1 *stub)
3686 CFREE(stub, COMPSTUB_SIZE * 8);
3690 /* function: createnativestub **************************************************
3692 creates a stub routine which calls a native method
3694 *******************************************************************************/
3696 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3697 #define NATIVESTUB_STACK 2
3698 #define NATIVESTUB_THREAD_EXTRA 5
3700 #define NATIVESTUB_STACK 1
3701 #define NATIVESTUB_THREAD_EXTRA 1
3704 #define NATIVESTUB_SIZE (54 + 4 + NATIVESTUB_THREAD_EXTRA - 1)
3705 #define NATIVESTUB_STATIC_SIZE 5
3706 #define NATIVESTUB_VERBOSE_SIZE (50 + 17)
3707 #define NATIVESTUB_OFFSET 10
3710 u1 *createnativestub(functionptr f, methodinfo *m)
3712 u8 *s; /* memory to hold the stub */
3714 s4 *mcodeptr; /* code generation pointer */
3715 s4 stackframesize = 0; /* size of stackframe if needed */
3720 t_inlining_globals *id;
3723 /* mark start of dump memory area */
3725 dumpsize = dump_size();
3727 /* setup registers before using it */
3729 cd = DNEW(codegendata);
3730 rd = DNEW(registerdata);
3731 id = DNEW(t_inlining_globals);
3733 inlining_setup(m, id);
3734 reg_setup(m, rd, id);
3736 method_descriptor2types(m); /* set paramcount and paramtypes */
3738 stubsize = NATIVESTUB_SIZE; /* calculate nativestub size */
3740 if ((m->flags & ACC_STATIC) && !m->class->initialized)
3741 stubsize += NATIVESTUB_STATIC_SIZE;
3744 stubsize += NATIVESTUB_VERBOSE_SIZE;
3746 s = CNEW(u8, stubsize); /* memory to hold the stub */
3747 cs = s + NATIVESTUB_OFFSET;
3748 mcodeptr = (s4 *) (cs); /* code generation pointer */
3750 /* set some required varibles which are normally set by codegen_setup */
3751 cd->mcodebase = (u1 *) mcodeptr;
3752 cd->patchrefs = NULL;
3754 *(cs-1) = (u8) f; /* address of native method */
3755 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3756 *(cs-2) = (u8) &builtin_get_exceptionptrptr;
3758 *(cs-2) = (u8) (&_exceptionptr); /* address of exceptionptr */
3760 *(cs-3) = (u8) asm_handle_nat_exception;/* addr of asm exception handler */
3761 *(cs-4) = (u8) (&env); /* addr of jni_environement */
3762 *(cs-5) = (u8) builtin_trace_args;
3764 *(cs-7) = (u8) builtin_displaymethodstop;
3765 *(cs-8) = (u8) m->class;
3766 *(cs-9) = (u8) asm_check_clinit;
3767 *(cs-10) = (u8) NULL; /* filled with machine code */
3769 M_LDA(REG_SP, REG_SP, -NATIVESTUB_STACK * 8); /* build up stackframe */
3770 M_LST(REG_RA, REG_SP, 0); /* store return address */
3772 /* if function is static, check for initialized */
3774 if (m->flags & ACC_STATIC && !m->class->initialized) {
3775 codegen_addpatchref(cd, mcodeptr, NULL, NULL);
3778 /* max. 50 instructions */
3783 M_LDA(REG_SP, REG_SP, -(18 * 8));
3784 M_AST(REG_RA, REG_SP, 1 * 8);
3786 /* save integer argument registers */
3787 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3788 M_LST(rd->argintregs[p], REG_SP, (2 + p) * 8);
3791 /* save and copy float arguments into integer registers */
3792 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3793 t = m->paramtypes[p];
3795 if (IS_FLT_DBL_TYPE(t)) {
3796 if (IS_2_WORD_TYPE(t)) {
3797 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3798 M_LLD(rd->argintregs[p], REG_SP, (10 + p) * 8);
3801 M_FST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3802 M_ILD(rd->argintregs[p], REG_SP, (10 + p) * 8);
3806 M_DST(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3810 M_ALD(REG_ITMP1, REG_PV, -6 * 8); /* method address */
3811 M_AST(REG_ITMP1, REG_SP, 0);
3812 M_ALD(REG_ITMP3, REG_PV, -5 * 8); /* builtin_trace_args */
3813 M_JSR(REG_RA, REG_ITMP3);
3815 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3816 M_LDA(REG_PV, REG_RA, disp);
3818 for (p = 0; p < m->paramcount && p < INT_ARG_CNT; p++) {
3819 M_LLD(rd->argintregs[p], REG_SP, (2 + p) * 8);
3822 for (p = 0; p < m->paramcount && p < FLT_ARG_CNT; p++) {
3823 t = m->paramtypes[p];
3825 if (IS_FLT_DBL_TYPE(t)) {
3826 if (IS_2_WORD_TYPE(t)) {
3827 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3830 M_FLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3834 M_DLD(rd->argfltregs[p], REG_SP, (10 + p) * 8);
3838 M_ALD(REG_RA, REG_SP, 1 * 8);
3839 M_LDA(REG_SP, REG_SP, 18 * 8);
3842 /* save argument registers on stack -- if we have to */
3843 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) || m->paramcount > (INT_ARG_CNT - 1)) {
3845 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3846 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3848 stackframesize = stackparamcnt + paramshiftcnt;
3850 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
3852 /* copy stack arguments into new stack frame -- if any */
3853 for (i = 0; i < stackparamcnt; i++) {
3854 M_LLD(REG_ITMP1, REG_SP, (stackparamcnt + 1 + i) * 8);
3855 M_LST(REG_ITMP1, REG_SP, (paramshiftcnt + i) * 8);
3858 if (m->flags & ACC_STATIC) {
3859 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
3860 M_DST(rd->argfltregs[5], REG_SP, 1 * 8);
3862 M_LST(rd->argintregs[5], REG_SP, 1 * 8);
3865 if (IS_FLT_DBL_TYPE(m->paramtypes[4])) {
3866 M_DST(rd->argfltregs[4], REG_SP, 0 * 8);
3868 M_LST(rd->argintregs[4], REG_SP, 0 * 8);
3872 if (IS_FLT_DBL_TYPE(m->paramtypes[5])) {
3873 M_DST(rd->argfltregs[5], REG_SP, 0 * 8);
3875 M_LST(rd->argintregs[5], REG_SP, 0 * 8);
3880 if (m->flags & ACC_STATIC) {
3881 M_MOV(rd->argintregs[5], rd->argintregs[7]);
3883 M_DMFC1(REG_ITMP1, rd->argfltregs[5]);
3884 M_DMTC1(REG_ITMP1, rd->argfltregs[7]);
3886 M_MOV(rd->argintregs[4], rd->argintregs[6]);
3888 M_DMFC1(REG_ITMP1, rd->argfltregs[4]);
3889 M_DMTC1(REG_ITMP1, rd->argfltregs[6]);
3891 M_MOV(rd->argintregs[3], rd->argintregs[5]);
3892 M_DMFC1(REG_ITMP1, rd->argfltregs[3]);
3894 M_MOV(rd->argintregs[2], rd->argintregs[4]);
3895 M_DMTC1(REG_ITMP1, rd->argfltregs[5]);
3897 M_MOV(rd->argintregs[1], rd->argintregs[3]);
3898 M_DMFC1(REG_ITMP1, rd->argfltregs[2]);
3900 M_MOV(rd->argintregs[0], rd->argintregs[2]);
3901 M_DMTC1(REG_ITMP1, rd->argfltregs[4]);
3903 M_DMFC1(REG_ITMP1, rd->argfltregs[1]);
3904 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
3906 M_DMFC1(REG_ITMP1, rd->argfltregs[0]);
3907 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
3909 M_ALD(rd->argintregs[1], REG_PV, -8 * 8);
3912 M_MOV(rd->argintregs[6], rd->argintregs[7]);
3914 M_DMFC1(REG_ITMP1, rd->argfltregs[6]);
3915 M_DMTC1(REG_ITMP1, rd->argfltregs[7]);
3917 M_MOV(rd->argintregs[5], rd->argintregs[6]);
3919 M_DMFC1(REG_ITMP1, rd->argfltregs[5]);
3920 M_DMTC1(REG_ITMP1, rd->argfltregs[6]);
3922 M_MOV(rd->argintregs[4], rd->argintregs[5]);
3923 M_DMFC1(REG_ITMP1, rd->argfltregs[4]);
3925 M_MOV(rd->argintregs[3], rd->argintregs[4]);
3926 M_DMTC1(REG_ITMP1, rd->argfltregs[5]);
3928 M_MOV(rd->argintregs[2], rd->argintregs[3]);
3929 M_DMFC1(REG_ITMP1, rd->argfltregs[3]);
3931 M_MOV(rd->argintregs[1], rd->argintregs[2]);
3932 M_DMTC1(REG_ITMP1, rd->argfltregs[4]);
3934 M_MOV(rd->argintregs[0], rd->argintregs[1]);
3935 M_DMFC1(REG_ITMP1, rd->argfltregs[2]);
3937 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
3939 M_DMFC1(REG_ITMP1, rd->argfltregs[1]);
3940 M_DMFC1(REG_ITMP2, rd->argfltregs[0]);
3942 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
3943 M_DMTC1(REG_ITMP2, rd->argfltregs[1]);
3946 M_ALD(rd->argintregs[0], REG_PV, -4 * 8); /* jni environement */
3947 M_ALD(REG_ITMP3, REG_PV, -1 * 8); /* load adress of native method */
3948 M_JSR(REG_RA, REG_ITMP3); /* call native method */
3949 M_NOP; /* delay slot */
3951 /* remove stackframe if there is one */
3952 if (stackframesize) {
3953 M_LDA(REG_SP, REG_SP, stackframesize * 8);
3956 /* 17 instructions */
3958 M_LDA(REG_SP, REG_SP, -(3 * 8));
3959 M_AST(REG_RA, REG_SP, 0 * 8);
3960 M_LST(REG_RESULT, REG_SP, 1 * 8);
3961 M_DST(REG_FRESULT, REG_SP, 2 * 8);
3962 M_ALD(rd->argintregs[0], REG_PV, -6 * 8);
3963 M_MOV(REG_RESULT, rd->argintregs[1]);
3964 M_DMFC1(REG_ITMP1, REG_FRESULT);
3965 M_DMTC1(REG_ITMP1, rd->argfltregs[2]);
3966 M_DMTC1(REG_ITMP1, rd->argfltregs[3]);
3967 M_ALD(REG_ITMP3, REG_PV, -7 * 8);/* builtin_displaymethodstop */
3968 M_JSR(REG_RA, REG_ITMP3);
3970 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3971 M_LDA(REG_PV, REG_RA, disp);
3972 M_ALD(REG_RA, REG_SP, 0 * 8);
3973 M_LLD(REG_RESULT, REG_SP, 1 * 8);
3974 M_DLD(REG_FRESULT, REG_SP, 2 * 8);
3975 M_LDA(REG_SP, REG_SP, 3 * 8);
3978 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3979 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* builtin_get_exceptionptrptr */
3980 M_JSR(REG_RA, REG_ITMP3);
3983 if (IS_FLT_DBL_TYPE(m->returntype)) {
3984 M_DST(REG_FRESULT, REG_SP, 1 * 8);
3987 M_AST(REG_RESULT, REG_SP, 1 * 8);
3990 M_MOV(REG_RESULT, REG_ITMP3);
3992 if (IS_FLT_DBL_TYPE(m->returntype)) {
3993 M_DLD(REG_FRESULT, REG_SP, 1 * 8);
3996 M_ALD(REG_RESULT, REG_SP, 1 * 8);
3999 M_ALD(REG_ITMP3, REG_PV, -2 * 8); /* get address of exceptionptr */
4002 M_LLD(REG_RA, REG_SP, 0); /* load return address */
4003 M_ALD(REG_ITMP1, REG_ITMP3, 0); /* load exception into reg. itmp1 */
4005 M_BNEZ(REG_ITMP1, 2); /* if no exception then return */
4006 M_LDA(REG_SP, REG_SP, NATIVESTUB_STACK * 8);/*remove stackframe, delay slot*/
4008 M_RET(REG_RA); /* return to caller */
4009 M_NOP; /* delay slot */
4011 M_AST(REG_ZERO, REG_ITMP3, 0); /* store NULL into exceptionptr */
4012 M_ALD(REG_ITMP3, REG_PV, -3 * 8); /* load asm exception handler address */
4014 M_JMP(REG_ITMP3); /* jump to asm exception handler */
4015 M_LDA(REG_ITMP2, REG_RA, -4); /* move fault address into reg. itmp2 */
4018 /* generate static stub call code */
4025 /* there can only be one clinit ref entry */
4026 pref = cd->patchrefs;
4029 /* Get machine code which is patched back in later. The call is */
4030 /* 2 instruction words long. */
4031 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4033 /* We need to split this, because an unaligned 8 byte read causes */
4035 *(cs-10) = ((u8) xcodeptr[1] << 32) + (u4) xcodeptr[0];
4037 /* patch in the call to call the following code (done at compile */
4040 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4041 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4043 M_BRS(tmpmcodeptr - (xcodeptr + 1));
4046 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4048 /* move class pointer into REG_ITMP1 */
4049 M_ALD(REG_ITMP1, REG_PV, -8 * 8); /* class */
4051 /* move machine code into REG_ITMP2 */
4052 M_LLD(REG_ITMP2, REG_PV, -10 * 8); /* machine code */
4054 M_ALD(REG_ITMP3, REG_PV, -9 * 8); /* asm_check_clinit */
4060 (void) docacheflush((void*) cs, (char*) mcodeptr - (char*) cs);
4062 /* Check if the stub size is big enough to hold the whole stub generated. */
4063 /* If not, this can lead into unpredictable crashes, because of heap */
4065 if ((s4) ((ptrint) mcodeptr - (ptrint) s) > stubsize * sizeof(u8)) {
4066 throw_cacao_exception_exit(string_java_lang_InternalError,
4067 "Native stub size %d is to small for current stub size %d",
4068 stubsize, (s4) ((ptrint) mcodeptr - (ptrint) s));
4071 #if defined(STATISTICS)
4073 count_nstub_len += NATIVESTUB_SIZE * 8;
4076 /* release dump area */
4078 dump_release(dumpsize);
4080 return (u1 *) (s + NATIVESTUB_OFFSET);
4084 /* function: removenativestub **************************************************
4086 removes a previously created native-stub from memory
4088 *******************************************************************************/
4090 void removenativestub(u1 *stub)
4092 CFREE((u8 *) stub - NATIVESTUB_OFFSET, NATIVESTUB_SIZE * 8);
4096 void docacheflush(u1 *p, long bytelen)
4098 u1 *e = p + bytelen;
4099 long psize = sysconf(_SC_PAGESIZE);
4100 p -= (long) p & (psize-1);
4101 e += psize - ((((long) e - 1) & (psize-1)) + 1);
4103 mprotect(p, bytelen, PROT_READ|PROT_WRITE|PROT_EXEC);
4108 * These are local overrides for various environment variables in Emacs.
4109 * Please do not remove this and leave it at the end of the file, where
4110 * Emacs will automagically detect them.
4111 * ---------------------------------------------------------------------
4114 * indent-tabs-mode: t